【问题标题】:Unity editor capture "hold mouse down and move" eventUnity 编辑器捕获“按住鼠标并移动”事件
【发布时间】:2020-07-22 17:49:13
【问题描述】:

我正在统一创建一个简单的 tilemap 编辑器扩展,因为默认的扩展缺少我的项目所需的许多功能。我正在继承 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;
    }
}

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

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

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

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

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

【问题讨论】:

  • 我可能像往常一样完全错了,但我认为不可能覆盖 Unity 内置行为。问题是整个点击和选择拖动可能在事件传递到您的自定义脚本之前已经被处理,因此它没有任何机会拦截它
  • @derHugo 也许是这样,但我想我想出了一些办法。

标签: c# unity3d


【解决方案1】:

好吧,所以我没有继承 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;
    }
}

【讨论】:

  • 是的,看起来很酷!很高兴知道显然有一种捕捉默认行为的方法。
猜你喜欢
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多