首页 >Unity3D频道 >【Unity杂文】 > Unity3D研究院之监听Hierachy、Project等视图结构变化的事件
2014
08-01

Unity3D研究院之监听Hierachy、Project等视图结构变化的事件

2015.06.15 补充

最近我发现了一个更好的方法来监听Project视图变化,欢迎大家前来看看 Unity3D研究院之监听Project视图结构变化的事件

以前就有人问我怎么监听Hierarchy视图中创建或删除变化的事件,当时因为有别的事情就没研究这块。刚好最近有这一类的需求我就学习学习。网上发现了一个日本人写的文档,实现的原理很有意思,内容不错我就翻译一下。

原文:http://anchan828.hatenablog.jp/entry/2013/12/29/015306

请注意一定把这两个监听的脚本放在Editor文件夹下。

先是基类。

using System;
using System.Collections;
using System.Reflection;
using UnityEditor;
using UnityEngine;
 
[InitializeOnLoad]
public class EditorMonoBehaviour
{
    static EditorMonoBehaviour ()
    {
        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); 
        var e = method.Invoke (null, new object[]{ typeof(EditorMonoBehaviour) }) as IEnumerable;
        foreach (Type editorMonoBehaviourClass in e) {
            method = editorMonoBehaviourClass.BaseType.GetMethod ("OnEditorMonoBehaviour", BindingFlags.NonPublic | BindingFlags.Instance);
            if (method != null) {
                method.Invoke (System.Activator.CreateInstance (editorMonoBehaviourClass), new object[0]);
            }
        }
    }
 
    private void OnEditorMonoBehaviour ()
    {
 
        EditorApplication.update += Update;
        EditorApplication.hierarchyWindowChanged += OnHierarchyWindowChanged;
        EditorApplication.hierarchyWindowItemOnGUI += HierarchyWindowItemOnGUI;
        EditorApplication.projectWindowChanged += OnProjectWindowChanged;
        EditorApplication.projectWindowItemOnGUI += ProjectWindowItemOnGUI;
        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);
 
 
        EditorApplication.searchChanged += OnSearchChanged;
 
        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
    }
}

接着是继承类,所有监听的事件在这里完成,两个类都不用实例化也不用NEW直接就可以监听。

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

思考:因为在这里我们只能得到它变化的事件,但是我们不知道哪个GameObject变化了。所以我觉得可以自己写一段代码来对比一下前后。 欢迎在下面给我留言,讨论与学习。谢谢。

最后编辑:
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!

Unity3D研究院之监听Hierachy、Project等视图结构变化的事件》有 6 条评论

  1. 雨松MOMO博客网友说:

    鼠标在Scene移动场景时,Transform的坐标值已经变化了,却没有触发OnHierarchyWindowChanged,请问要怎么才能监听变化呢?

  2.  说:

    鼠标在Scene移动场景时,Transform的坐标值已经变化了,却没有触发OnHierarchyWindowChanged,请问要怎么才能监听变化呢?

  3. 冯乐乐说:

    怎么前后对比找到变化、新增或删除的对象呢?

留下一个回复

你的email不会被公开。 必填项已用 * 标注。