【问题标题】:How to use Unity editor script to drag asset object to Scene View like Unity editor > Project view如何使用 Unity 编辑器脚本将资产对象拖动到 Unity 编辑器 > 项目视图等场景视图
【发布时间】:2018-09-24 03:25:53
【问题描述】:

例如,我发现 Unity 插件“Octave3d 关卡设计”有这个功能

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

【问题讨论】:

    标签: c# unity3d unity-editor


    【解决方案1】:

    编辑: 实际上发现你需要使用 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;
            }
    

    【讨论】:

    • 更新信息
    【解决方案2】:

    在Octave3d,他们通过以下方式实现了这个功能:

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

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

    1. 在您的自定义编辑器窗口中,收听MouseDownEvent 以启动 DragAndDrop
    2. 在您的自定义编辑器窗口中,听DragUpdatedEvent 移动拖动对象
    3. 如果您想检测 SceneView 或 Hierarchy 上的 Dropping,请在 ongui 回调中收听 DragPerform 和 DragExited。

    代码在这里:

    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

    【讨论】:

      猜你喜欢
      • 2023-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-08
      • 1970-01-01
      相关资源
      最近更新 更多