之前上网看了MOMO关于监听Hierachy、Project等视图结构变化的事件,原代码是一个日本人写的,MOMO也没有讲原理。这里我通过自己的理解加了些注释,可能有不正确的地方,希望大神指点。
其中用到了[InitializeOnLoad],可以监听Unity的启动事件,在启动Unity的时候运行编辑器脚本。需要静态的构造函数! 这是下面的代码中EditorMonoBehaviour构造函数为什么是static的原因。
using System;
using System.Collections;
using System.Reflection;
using UnityEditor;
using UnityEngine;
[InitializeOnLoad]
public class EditorMonoBehaviour
{
static EditorMonoBehaviour ()
{
//获取UnityEditor.EditorAssemblies中的SubclassesOf方法
var type = Types.GetType ("UnityEditor.EditorAssemblies", "UnityEditor.dll");
var method = type.GetMethod ("SubclassesOf", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[]{ typeof(Type) }, null);
//调用SubclassesOf方法获得所有继承于EditorMonoBehaviour的类
var e = method.Invoke (null, new object[]{ typeof(EditorMonoBehaviour) }) as IEnumerable;
foreach (Type editorMonoBehaviourClass in e) {
//获取editorMonoBehaviourClass即继承于EditorMonoBehaviour的类中的OnEditorMonoBehaviour方法
method = editorMonoBehaviourClass.BaseType.GetMethod ("OnEditorMonoBehaviour", BindingFlags.NonPublic | BindingFlags.Instance);
//创建实例并调用editorMonoBehaviourClass中的OnEditorMonoBehaviour方法
if (method != null) {
method.Invoke (System.Activator.CreateInstance (editorMonoBehaviourClass), new object[0]);
}
}
}
private void OnEditorMonoBehaviour ()
{
EditorApplication.update += Update;
//Each time an object is (or a group of objects are) created, renamed, parented, unparented or destroyed this callback is raised.
EditorApplication.hierarchyWindowChanged += OnHierarchyWindowChanged;
//Delegate for OnGUI events for every visible list item in the HierarchyWindow.
EditorApplication.hierarchyWindowItemOnGUI += HierarchyWindowItemOnGUI;
//Callback raised whenever the state of the Project window changes.
EditorApplication.projectWindowChanged += OnProjectWindowChanged;
//Delegate for OnGUI events for every visible list item in the ProjectWindow.
EditorApplication.projectWindowItemOnGUI += ProjectWindowItemOnGUI;
//Delegate for changed keyboard modifier keys
EditorApplication.modifierKeysChanged += OnModifierKeysChanged;
// globalEventHandler
EditorApplication.CallbackFunction function = () => OnGlobalEventHandler (Event.current);
FieldInfo info = typeof(EditorApplication).GetField ("globalEventHandler", BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic);
EditorApplication.CallbackFunction functions = (EditorApplication.CallbackFunction)info.GetValue (null);
functions += function;
info.SetValue (null, (object)functions);
//Callback raised whenever the contents of a window's search box are changed.
EditorApplication.searchChanged += OnSearchChanged;
//Delegate for play mode state changes.
EditorApplication.playmodeStateChanged += () => {
if (EditorApplication.isPaused) {
OnPlaymodeStateChanged (PlayModeState.Paused);
}
if (EditorApplication.isPlaying) {
OnPlaymodeStateChanged (PlayModeState.Playing);
}
if (EditorApplication.isPlayingOrWillChangePlaymode) {
OnPlaymodeStateChanged (PlayModeState.PlayingOrWillChangePlaymode);
}
};
}
public virtual void Update ()
{
}
public virtual void OnHierarchyWindowChanged ()
{
}
public virtual void HierarchyWindowItemOnGUI (int instanceID, Rect selectionRect)
{
}
public virtual void OnProjectWindowChanged ()
{
}
public virtual void ProjectWindowItemOnGUI (string guid, Rect selectionRect)
{
}
public virtual void OnModifierKeysChanged ()
{
}
public virtual void OnGlobalEventHandler (Event e)
{
}
public virtual void OnSearchChanged ()
{
}
public virtual void OnPlaymodeStateChanged (PlayModeState playModeState)
{
}
public enum PlayModeState
{
Playing,
Paused,
Stop,
PlayingOrWillChangePlaymode
}
}
子类:就不加注释了,理解起来很简单
using UnityEditor;
using UnityEngine;
public class NewBehaviourScript : EditorMonoBehaviour
{
public override void Update ()
{
//Debug.Log ("每一帧回调一次");
}
public override void OnPlaymodeStateChanged (PlayModeState playModeState)
{
Debug.Log ("游戏运行模式发生改变, 点击 运行游戏 或者暂停游戏或者 帧运行游戏 按钮时触发: " + playModeState);
}
public override void OnGlobalEventHandler (Event e)
{
Debug.Log ("全局事件回调: " + e);
}
public override void HierarchyWindowItemOnGUI (int instanceID, Rect selectionRect)
{
Debug.Log (string.Format ("{0} : {1} - {2}", EditorUtility.InstanceIDToObject (instanceID), instanceID, selectionRect));
}
public override void OnHierarchyWindowChanged ()
{
Debug.Log ("层次视图发生变化");
}
public override void OnModifierKeysChanged ()
{
Debug.Log ("当触发键盘事件");
}
public override void OnProjectWindowChanged ()
{
Debug.Log ("当资源视图发生变化");
}
public override void ProjectWindowItemOnGUI (string guid, Rect selectionRect)
{
//根据GUID得到资源的准确路径
// Debug.Log (string.Format ("{0} : {1} - {2}", AssetDatabase.GUIDToAssetPath (guid), guid, selectionRect));
}
}