比如我发现Unity插件“Octave3d Level Design”就有这个功能
我希望制作自己的预制管理器,因为 Octave3d 预制管理器不适合我的需要。那么问题来了:当鼠标在Scene View上重叠时,如何让鼠标抓住一个物体放到Scene View中呢?
编辑:实际上发现你需要使用 SceneView.lastActiveSceneView.camera 作为你的相机,你可以使用 Gizmos.DrawMesh() 来绘制网格而不是实例化..
还有 SceneView.OnSceneGUIDelegate 可以帮助您访问场景视图。
这是一些关于如何设置的示例代码
void OnGUI() {
if (objectThatFollowsMouse != null) {
SceneView.onSceneGUIDelegate -= OnSceneGUI;
SceneView.onSceneGUIDelegate += OnSceneGUI;
}
else { SceneView.onSceneGUIDelegate -= OnSceneGUI; }
}
void OnSceneGUI(SceneView sceneView) {
...
}
使用一些额外的编辑器脚本,你可以做这样的事情
Vector3 mousePoint = Camera.main.ViewportToWorldPoint(Input.mousePosition);
if (objectShouldFollowMouse) {
objectThatFollowsMouse.transform.position = mousePoint;
if (Event.current.type == EventType.MouseUp) {
objectShouldFollowMouse = false;
objectThatFollowsMouse = null;
}
}
if (prefabGotClicked) {
GameObject obj = Object.Instantiate(someObject,mousePoint,Quaternion.identity) as GameObject;
objectShouldFollowMouse = true;
objectThatFollowsMouse = obj;
}
在Octave3d
中,他们通过以下方式实现了此功能:
preview
,在场景中实例化预制件的游戏对象,预览游戏对象将跟随鼠标(通过他们自定义的光线投射检测)。预览游戏对象的父级是八度管理器或类似的东西。而且我认为这有点矫枉过正,像 Unity 自己的 DragAndDrop 这样的东西就足够了:可以从自定义编辑器窗口拖动预制件,然后放到场景视图、层次结构或对象字段上。这个自定义拖放可以像这样实现:
MouseDownEvent
启动 DragAndDropDragUpdatedEvent
移动拖动对象Dropping
on SceneView 或 Hierarchy,请收听DragPerform
onguiDragExited
回调。代码在这里:
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
public class MyWindow : EditorWindow
{
[MenuItem("Window/MyWindow")]
private static void ShowWindow()
{
GetWindow<MyWindow>("MyWindow");
}
private GameObject prefab;
private bool m_IsDragPerformed = false;
private bool m_IsDragging = false;
private void OnEnable()
{
prefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Cube.prefab");
var box = new VisualElement();
box.style.backgroundColor = Color.red;
box.style.flexGrow = 1f;
box.RegisterCallback<MouseDownEvent>(evt =>
{
DragAndDrop.PrepareStartDrag();
DragAndDrop.StartDrag("Dragging");
DragAndDrop.objectReferences = new Object[] { prefab };
Selection.activeGameObject = null;
m_IsDragPerformed = false;
m_IsDragging = true;
});
box.RegisterCallback<DragUpdatedEvent>(evt =>
{
DragAndDrop.visualMode = DragAndDropVisualMode.Move;
});
rootVisualElement.Add(box);
SceneView.duringSceneGui += sv => OnDragEnd();
EditorApplication.hierarchyWindowItemOnGUI += (id, rect) => OnDragEnd();
}
private void OnDragEnd()
{
if (Event.current.type == EventType.DragPerform)
{
m_IsDragPerformed = true;
}
if (Event.current.type == EventType.DragExited)
{
if (m_IsDragging && m_IsDragPerformed)
{
m_IsDragging = false;
m_IsDragPerformed = false;
var go = Selection.activeGameObject;
// Do your **OnDragEnd callback on go** here
}
}
}
private void OnDestroy()
{
SceneView.duringSceneGui -= sv => OnDragEnd();
EditorApplication.hierarchyWindowItemOnGUI -= (id, rect) => OnDragEnd();
}
}
参考在这里,这家伙是个天才:How to start DragAndDrop action so that SceneView and Hierarchy accept it like with prefabs