【发布时间】:2018-09-24 03:25:53
【问题描述】:
例如,我发现 Unity 插件“Octave3d 关卡设计”有这个功能
我希望自己做一个预制管理器,因为 Octave3d 预制管理器不适合我的需要。那么问题来了:当鼠标在Scene View上重叠时,如何让鼠标抓住一个物体放到Scene View中?
【问题讨论】:
标签: c# unity3d unity-editor
例如,我发现 Unity 插件“Octave3d 关卡设计”有这个功能
我希望自己做一个预制管理器,因为 Octave3d 预制管理器不适合我的需要。那么问题来了:当鼠标在Scene View上重叠时,如何让鼠标抓住一个物体放到Scene View中?
【问题讨论】:
标签: c# unity3d unity-editor
编辑: 实际上发现你需要使用 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,请在 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
【讨论】: