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

3
我正在使用Unity创建一个简单的瓦片地图编辑器扩展,因为默认的编辑器缺少我项目所需的很多功能。我继承了EditorWindow类。 当按住左键并拖动鼠标时,我想在场景中放置瓦片(在编辑器模式下)。
下面的图片说明了我想要的行为。

enter image description here:

我可以帮您进行翻译。以下是您需要翻译的内容:

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

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;
    }
}

第一个案例(单个瓦片放置)按预期工作。但我无法捕获“按住左键”事件。我可以捕获鼠标移动事件EventType.MouseMove,但我需要知道是否有左击。根据Unity文档,e.button == 0表示左击(在第一个switch case中按预期工作)。但在第二个case中,无论点击哪个鼠标按钮,e.button始终为0。还有一个EventType.MouseDrag,但似乎只有在选择场景中的游戏对象并拖动时才会触发。
在Unity中,当按住左键并移动鼠标时,默认行为似乎是创建选择框:

enter image description here

如果在编辑器左上角选择手的图标,则可以拖动整个场景。

实际上,我想捕获此事件并用自己的功能覆盖结果。

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


我可能像往常一样完全错误,但我认为不可能覆盖Unity内置的行为。问题在于整个点击和选择拖动可能已经在事件传递到您的自定义脚本之前处理完毕,因此它将没有任何机会进行拦截。 - derHugo
@derHugo 或许是这样,但我认为我成功想出了一些东西。 - Tagor
1个回答

6

好的,所以我没有继承EditorWindow而是创建了一个自定义工具TileTool并把所有逻辑放在那里。

在它的OnToolGUI(相当于OnGUI?)中我可以禁用框选:

HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive));

自动魔法般地捕获了事件 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;
    }
}

1
是的,看起来很酷!很高兴知道显然有一种方法可以捕获默认行为。 - derHugo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接