1

比如我发现Unity插件“Octave3d Level Design”就有这个功能 在此处输入图像描述

我希望制作自己的预制管理器,因为 Octave3d 预制管理器不适合我的需要。那么问题来了:当鼠标在Scene View上重叠时,如何让鼠标抓住一个物体放到Scene View中呢?

4

2 回答 2

2

编辑:实际上发现你需要使用 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;
        }
于 2018-09-24T03:38:12.180 回答
0

Octave3d中,他们通过以下方式实现了此功能:

  1. 当在自定义编辑器窗口中选择预制件时preview,在场景中实例化预制件的游戏对象,预览游戏对象将跟随鼠标(通过他们自定义的光线投射检测)。预览游戏对象的父级是八度管理器或类似的东西。
  2. 在场景中单击时,在鼠标场景的交点处实例化场景中的另一个游戏对象。

而且我认为这有点矫枉过正,像 Unity 自己的 DragAndDrop 这样的东西就足够了:可以从自定义编辑器窗口拖动预制件,然后放到场景视图、层次结构或对象字段上。这个自定义拖放可以像这样实现:

  1. 在您的自定义编辑器窗口中,听MouseDownEvent启动 DragAndDrop
  2. 在您的自定义编辑器窗口中,听DragUpdatedEvent移动拖动对象
  3. 如果要检测Droppingon SceneView 或 Hierarchy,请收听DragPerformonguiDragExited回调。

代码在这里:

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

于 2021-01-11T04:17:59.540 回答