using System; using System.Collections.Generic; using UnityEditor; using UnityEngine; /// /// 在多 SceneView 窗口下安全地添加/移除临时回调。 /// 原理:Templist 存放需在下一帧执行的回调,OnSceneGUI 将会把 Templist 转移到 list 来执行。 /// public class UXCustomSceneView { static private List> list = new List>(); static private List> Templist = new List>(); [InitializeOnLoadMethod] static void Init() { list.Clear(); Templist.Clear(); SceneView.duringSceneGui -= OnSceneGUI; SceneView.duringSceneGui += OnSceneGUI; } static public void AddDelegate(Action method) { if (method == null) return; // 去重 if (!Templist.Contains(method)) Templist.Add(method); } static public void RemoveDelegate(Action method) { if (method == null) return; var idx = Templist.FindIndex(i => i == method); if (idx >= 0) Templist.RemoveAt(idx); } static public void OnSceneGUI(SceneView sceneView) { // 执行上一帧注册的 list foreach (Action method in list) { try { method.Invoke(sceneView); } catch (Exception e) { Debug.LogException(e); } } list.Clear(); // 将 Templist 拷贝到 list,并在下一帧执行,这样可以避免在枚举时修改集合的问题 foreach (Action method in Templist) { if (!list.Contains(method)) list.Add(method); } } static public void ClearDelegate() { Templist.Clear(); } }