最近希望在编辑器模式下通过GameView的鼠标操作镜头,所以首先需要获取到鼠标的操作事件
编辑器模式下运行一般来有监听EditorApplication.update回调,或者 在MonoBehaviour的类声明[ExecuteInEditMode]、[ExecuteAlways]标签两种方式。获取鼠标方式一般有Input和Event两种方式,下面直接说在编辑器模式下的组合结果
1.监听EditorApplication.update回调的方式:
无法使用Input(Input.touchCount = 0)
无法使用 Event(Event.current = null)
2.标签的方式:
无法使用Input(Input.touchCount = 0)
可以在如OnGUI的一些函数中获取鼠标坐标(Event.current.mousePosition),但无法获取具体鼠标行为(Event.current.type 只有Repaint和Layout)
所以需要其他实现方式:
Event的其他应用场景
1.在继承了UnityEditor.Editor类的如OnInspector函数中使用
2.在继承了UnityEditor.EditorWindow类的如OnGUI函数中使用
GameView也是继承了EditorWindow的窗口,下面是反编译后的代码
上面GameView自己也在OnGUI函数中使用的Event进行了一些事件处理,所以我们只要截获它的OnGUI事件即可。
1.GameView是UnityEditor的内置类,访问它可以使用反射,或者注入友元程序集的方式+桥接的方式(本文使用的方式)
2.截获OnGUI函数,可以使用Hook的方式,最后我的核心代码如下:
using System.Runtime.CompilerServices; using UnityEngine; using UnityEditor; namespace TBC.Editor.Hook { public class TBCHook_GameView { public static System.Action onGUI; [MethodImpl(MethodImplOptions.NoOptimization)] private void OnGUI_Origin() { } [TBCHook(typeof(GameView), "File: UnityEditor.GameView.cs OnGUI")] [MethodImpl(MethodImplOptions.NoOptimization)] private void OnGUI() { Debug.Log(UnityEngine.Event.current.type); if (onGUI != null) onGUI(); OnGUI_Origin(); } } }
这里我注入的是友元类Timeline程序集
TBCHook标签是我对Hook调用的一种封装方式(Hook代码地址)
这样外部内可以通过注册事件监听获取到GameView的OnGUI函数,可以在上面再套一层你自己的事件管理类(比如XXEventManager)来同时处理Editor与Runtime的所有鼠标操作事件
最终结果
文章评论