Unity编辑器捕获“按住鼠标并移动”事件

Tag*_*gor 3 c# unity-game-engine

我正在统一创建一个简单的图块地图编辑器扩展,因为默认的扩展缺乏我的项目需要的很多功能。我正在继承EditorWindow。按住鼠标左键并拖动鼠标时,我想在场景中放置图块(在编辑器模式下)。

下图说明了我想要的行为。

在此输入图像描述:

我面临的问题是如何识别这个事件。这是我使用的处理鼠标输入的函数:

void HandleMouseInput() {
    Event e = Event.current;
    switch (e.type) {
    case EventType.MouseDown:
        if (e.button == 0) PlaceTile();
        break;
    case EventType.MouseMove:
        Debug.Log("Moving");
        Debug.Log(e.button); // <-- always show 0 (left click) even though mouse is not clicked.
        break;
    }
}
Run Code Online (Sandbox Code Playgroud)

第一种情况(单块放置)按预期工作。但我未能捕获“按住鼠标左键”事件。我可以捕获鼠标移动事件EventType.MouseMove,但然后我需要是否有左键单击。根据统一文档,e.button == 0表示左键单击(在第一个开关情况下按预期工作)。但在第二种情况下e.button,无论单击哪个鼠标按钮,始终为 0。还有一个EventType.MouseDrag,但它似乎只有当您在场景中选择一个游戏对象并拖动它时才会触发。

在 Unity 中,当按住鼠标左键并移动鼠标时,默认行为似乎是创建一个选择框:

在此输入图像描述

或者,如果在编辑器左上角选择了手形图标,则拖动整个场景。

本质上我想捕获这个事件并用我自己的功能覆盖结果。

编辑:我想我可以通过创建自定义工具来解决这个问题https://docs.unity3d.com/ScriptReference/EditorTools.EditorTool.html

Tag*_*gor 6

好吧,我没有继承 EditorWindow,而是创建了一个自定义工具 TileTool 并将所有逻辑放在其中。

在其 OnToolGUI(OnGUI 等效项?)中,我可以禁用框选择:

HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive));
Run Code Online (Sandbox Code Playgroud)

EventType.MouseDrag并自动正确捕获事件,我达到了预期的效果。

整个脚本:

[EditorTool("Tile Tool")]
class TileTool : EditorTool
{
    // Serialize this value to set a default value in the Inspector.
    [SerializeField]
    Texture2D icon;



    public override GUIContent toolbarIcon =>
        new GUIContent() {
            image = icon,
            text = "Tile Tool",
            tooltip = "Tile Tool"
        };


    public override void OnToolGUI(EditorWindow window) {
        HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive));
        HandleMouse();
    }

    void HandleMouse() {
        Event e = Event.current;
        switch (e.type) {
            case EventType.MouseDown:
                if (e.button == 0) ApplyLeftClickTool();
                break;
            case EventType.MouseDrag:
                if (e.button == 0) ApplyLeftClickTool();
                break;
        }
    }



    void ApplyLeftClickTool() {
        switch (TilemapEditor.Instance().ActiveTool) {
        case TilemapEditor.TileTool.BRUSH:
                PlaceTile();
                break;
        case TilemapEditor.TileTool.ERASER:
                EraseTile();
                break;
        }
    }

    void PlaceTile() {
        GameObject prefab = TilemapEditor.Instance().Selected;
        GetTilemap().Place(prefab, MouseInWorld());
    }

    void EraseTile() {
        GetTilemap().Erase(MouseInWorld());
    }

    PrefabTilemap GetTilemap() {
        PrefabTilemap tilemap = FindObjectOfType<PrefabTilemap>();
        if (tilemap == null) {
            GameObject tilemapGO = new GameObject("Tilemap");
            tilemap = tilemapGO.AddComponent<PrefabTilemap>();
            tilemap.Init();
        }
        return tilemap;
    }

    Vector2 MouseInWorld() {
        return HandleUtility.GUIPointToWorldRay(Event.current.mousePosition).origin;
    }
}
Run Code Online (Sandbox Code Playgroud)