1. 程式人生 > >Unity監聽Hierachy檢視變化

Unity監聽Hierachy檢視變化

經過一番百度我找到了兩種方法。

一、是EditorWindow.OnHierarchyChang這種要建立一個視窗,而且這個視窗關閉了就失效了,不管那麼多來看實現程式碼:

using UnityEngine;
using System.Collections;
using UnityEditor;

public class HierachyChange : EditorWindow {
    [MenuItem("Tools/HierachyChangeWindow")]
    static void AddWindow()
    {
        Rect wr = new Rect(0, 0, 500, 500);
        HierachyChange window = (HierachyChange)EditorWindow.GetWindowWithRect(typeof(HierachyChange), wr, true, "widow name");
        window.Show();
    }
    void OnHierarchyChange()
    {
        Debug.Log("當Hierarchy檢視中的任何物件發生改變時呼叫一次,改變後儲存當前場景還會呼叫一次");
    }

}
該指令碼要放在Editor資料夾下。

二、是我在雨鬆MOMO的一篇文章裡看到的,這裡我也把他的程式碼貼出來,有興趣的可以去他的原文http://www.xuanyusong.com/archives/3053  註明:以下程式碼出自  雨鬆MOMO的Unity3D研究院之監聽Hierachy、Project等檢視結構變化的事件這篇文章:

//這個是基類

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
    }
}
下面是子類他實現了上面的虛擬函式。
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));
    }
}
把這兩個類放在Editor資料夾裡就行了。