如何使用Unity编辑器脚本将资产对象拖到场景视图,例如Unity编辑器>项目视图

时间:2018-09-24 03:25:53

标签: c# unity3d unity-editor

例如,我发现Unity插件“ Octave3d Level Design”具有此功能 enter image description here

由于Octave3d预制管理器不适合我的需求,所以我希望成为自己的预制管理器。所以问题是:当鼠标与“场景视图”重叠时,如何使鼠标抓住一个对象并将其放入“场景视图”中?

2 个答案:

答案 0 :(得分: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;
        }

答案 1 :(得分:0)

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

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

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

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

代码在这里:

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