diff --git a/CHANGELOG.md b/CHANGELOG.md index 649ef7b..859ae54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,29 @@ # Changelog -## [UnRealse] +## [0.5.3] - 2025-09-26 + +添加一个大顶堆数据容器XericLibrary.Runtime.Type.SpatialAlgorithm.MaxHeap +添加一个untiy委托测试脚本XericLibrary.Runtime.Type.SpatialAlgorithm.BenchMarker +超级单例 +* 对超级单例进行详细注释。 + +对象库 +* 添加了在节点上获取兄弟节点的功能。 +* 添加在节点兄弟节点上获取组件的功能。 + +对象池 +* 完善UnionSet对象池在动态生成情况下对脏数据的处理,可以更好处理动态情况下切换实例时的情景。 +* 联合对象池不再强制要求手动初始化,而是自动推迟到首次获取时。 +* 修复对象池在间接释放对象时,可能找不到对象的问题 + +列表库 +* 加入了Repeat方法。 + +对weakly稍作优化。 +修复togglemapping在处理通过索引激活时的条件问题。 +在超链接管理器上添加了一个刷新的测试方法。 + +## [0.5.2] - 2025-09-03 修复富文本包裹器中SpriteBlock在处理颜色元素时选择到错误下标的问题。 增加了一些windows窗口命令。 @@ -10,12 +33,15 @@ * 添加了迭代重复 * 差异比较库添加了通过数量比较(也支持替换) * 添加了更多merge语法,支持合并类与输出类类型不一致 +* 修复foreachDo迭代用法中内插语法的用法。现在启用内插后可以正确输出了。同时允许使用null代替action了。 +* 添加编组输出条件,支持手动定义委托触发,相等性触发。 +* 添加连续计数。 文件库 * 添加了获取目标路径上的文件名和路径名 * 添加对文件路径修复的方法,比如untiy路径是/拼接,windowsPath使用\拼接,混用会错误的问题。 -## [0.5.1] +## [0.5.1] - 2025-08-05 修复反射库钟使用方法类型检查时,产生数组越界,或空引用问题,这会在部分匿名转换过程中发生。 修复使用匿名对象赋值时,如果类型不匹配会报错的问题,现在改为了产生警告。 diff --git a/Editor/DeconstructionStyle.dll.meta b/Editor/DeconstructionStyle.dll.meta index c75c2cb..dc9d62d 100644 --- a/Editor/DeconstructionStyle.dll.meta +++ b/Editor/DeconstructionStyle.dll.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: bcbfe98d29b703044a524e421fcacc2a +guid: 114790f70dba8284a84b68083baa8418 PluginImporter: externalObjects: {} serializedVersion: 2 diff --git a/Editor/DeconstructionStyle.pdb.meta b/Editor/DeconstructionStyle.pdb.meta index 0722b88..c1fa59e 100644 --- a/Editor/DeconstructionStyle.pdb.meta +++ b/Editor/DeconstructionStyle.pdb.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 6116f350f3c2bca4dbb63afc5febe614 +guid: e705db20b7214dc4cbfe3089b7219737 DefaultImporter: externalObjects: {} userData: diff --git a/Editor/XericLibraryEditor.dll b/Editor/XericLibraryEditor.dll index 81349be..39445bf 100644 Binary files a/Editor/XericLibraryEditor.dll and b/Editor/XericLibraryEditor.dll differ diff --git a/Editor/XericLibraryEditor.dll.meta b/Editor/XericLibraryEditor.dll.meta index 18b27e0..65a945a 100644 --- a/Editor/XericLibraryEditor.dll.meta +++ b/Editor/XericLibraryEditor.dll.meta @@ -11,53 +11,17 @@ PluginImporter: isExplicitlyReferenced: 0 validateReferences: 1 platformData: - - first: - : Any - second: - enabled: 0 - settings: - Exclude Editor: 0 - Exclude Linux64: 1 - Exclude OSXUniversal: 1 - Exclude Win: 1 - Exclude Win64: 1 - first: Any: second: - enabled: 1 + enabled: 0 settings: {} - first: Editor: Editor second: enabled: 1 settings: - CPU: AnyCPU DefaultValueInitialized: true - OS: AnyOS - - first: - Standalone: Linux64 - second: - enabled: 0 - settings: - CPU: AnyCPU - - first: - Standalone: OSXUniversal - second: - enabled: 0 - settings: - CPU: None - - first: - Standalone: Win - second: - enabled: 0 - settings: - CPU: x86 - - first: - Standalone: Win64 - second: - enabled: 0 - settings: - CPU: x86_64 - first: Windows Store Apps: WindowsStoreApps second: diff --git a/Runtime/Deconstruction.dll b/Runtime/Deconstruction.dll index e40db4b..e0a90cd 100644 Binary files a/Runtime/Deconstruction.dll and b/Runtime/Deconstruction.dll differ diff --git a/Runtime/Deconstruction.pdb.meta b/Runtime/Deconstruction.pdb.meta index 8f50744..c4f8a22 100644 --- a/Runtime/Deconstruction.pdb.meta +++ b/Runtime/Deconstruction.pdb.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 8acde5da4f147914f835131d166274df +guid: c67d7ef6c97613b41b9095a945725e91 DefaultImporter: externalObjects: {} userData: diff --git a/Runtime/Helper/MacroLayout.cs.meta b/Runtime/Helper/MacroLayout.cs.meta index 9cad9aa..e282462 100644 --- a/Runtime/Helper/MacroLayout.cs.meta +++ b/Runtime/Helper/MacroLayout.cs.meta @@ -1,3 +1,3 @@ fileFormatVersion: 2 -guid: 3f162d80c71a441780f9bc255eb5e169 +guid: 34832ce232e3acf45b7ca41349d5515e timeCreated: 1734339863 \ No newline at end of file diff --git a/Runtime/SerializerHelper.pdb.meta b/Runtime/SerializerHelper.pdb.meta index 6c8f9c3..dffc3ef 100644 --- a/Runtime/SerializerHelper.pdb.meta +++ b/Runtime/SerializerHelper.pdb.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 62d0397e1e24f0748a58f4046b547552 +guid: 5a61f0f8f8df56c42af4507d63579616 DefaultImporter: externalObjects: {} userData: diff --git a/Runtime/UI/MacroUI.cs b/Runtime/UI/MacroUI.cs index 47fcce0..2c6edf3 100644 --- a/Runtime/UI/MacroUI.cs +++ b/Runtime/UI/MacroUI.cs @@ -3,9 +3,12 @@ using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; +using Deconstruction.UI.Interface; using TMPro; using UnityEngine; using UnityEngine.Events; +using UnityEngine.Pool; +using UnityEngine.Serialization; using UnityEngine.UI; using XericLibrary.Runtime.CustomEditor; @@ -31,6 +34,17 @@ namespace XericLibrary.Runtime.MacroLibrary private static FieldInfo togglesFieldInfo = typeof(ToggleGroup).GetField("m_Toggles", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + /// + /// 获取给定单选项组中的所有单选项目 + /// + /// + /// 注意:操作具有一定的危险性,你可以自行制作这个列表对象的拷贝,但注意不要直接对返回的列表对象进行操作。 + /// + /// + /// + /// + /// + /// public static List GetToggles(this ToggleGroup toggleGroup) { if (toggleGroup == null) @@ -114,6 +128,50 @@ namespace XericLibrary.Runtime.MacroLibrary #region toggle 索引 + [Serializable] + public class ToggleValueMapping : ToggleMapping + { + #region 事件委托 + + public Action OnAnyToggleValueSwitchOn; + + #endregion + + #region 字段属性 + +#if ODIN_INSPECTOR + [SerializeField, LabelText("编辑单选项目值")] +#endif + private List toggleValue; + + #endregion + + public override void BakeToggleGroupItems() + { + base.BakeToggleGroupItems(); + if (toggleValue is not { Count: > 0 } || toggleValue.Count != toggleList.Count) + { + toggleValue = new List(); + for (var i = 0; i < toggleList.Count; i++) + toggleValue.Add(default(T)); + } + } + + public T GetValueByIndex(int index) + { + if (toggleValue is not { Count: > 0 } || index < 0 || index >= toggleValue.Count) + return default; + return toggleValue[index]; + } + + protected override void ToggleRegister(Toggle t) + { + base.ToggleRegister(t); + OnAnyToggleValueSwitchOn?.Invoke(t, GetValueByIndex(GetIndex(t))); + } + } + + /// /// toggle映射集 /// @@ -121,7 +179,7 @@ namespace XericLibrary.Runtime.MacroLibrary /// /// [Serializable] - public class ToggleMapping : IEnumerable + public class ToggleMapping : IEnumerable, IHierarchyControl { #region 事件委托 @@ -138,103 +196,191 @@ namespace XericLibrary.Runtime.MacroLibrary #endregion #region 字段属性 + #if ODIN_INSPECTOR - [LabelText("单选组")] + [LabelText("单选组")] #endif public ToggleGroup ToggleGroup; -#if ODIN_INSPECTOR - [SerializeField, LabelText("编辑单选项目顺序")] [ListDrawerSettings(OnTitleBarGUI = "GetAndSortToggle")] +#if ODIN_INSPECTOR + [LabelText("编辑单选项目顺序")] #endif - private List toggleList = new List(); + [SerializeField] + protected List toggleList = new List(); - // 当前选中的项目 - private int nowSelectToggleIndex = 0; - private Toggle nowSelectToggle = null; - - - public Transform TogglesContext => ToggleGroup.transform; - - /// - /// 当前选中的toggle索引 - /// - public int NowSelectToggleIndex => nowSelectToggleIndex; - - /// - /// 当前选中的toggle - /// - public Toggle NowSelectToggle => nowSelectToggle; - - - /// - /// 获取并给列表排序(顺序不一定与拼音有关) - /// - public void GetAndSortToggle() + protected bool ToggleListInvalid => toggleList is not { Count: > 0 }; + + public List ToggleList { -#if UNITY_EDITOR && ODIN_INSPECTOR - // 自动获取并排序 - if (SirenixEditorGUI.ToolbarButton(EditorIcons.Refresh)) + get { - GetSortToggle(); - } - // 反转顺序 - if (SirenixEditorGUI.ToolbarButton(EditorIcons.TriangleDown)) - { - toggleList.Reverse(); - } -#else - GetSortToggle(); +#if UNITY_EDITOR + if (!Application.isPlaying) + return toggleList; #endif - void GetSortToggle() - { - var newToggleList = MacroSort.FullCharacterOrderSort(ToggleGroup.GetToggles(), a => a.name) - .ToList(); - if (newToggleList.Count <= 0 || newToggleList == null) - Debug.LogError("如果无法更新获取自动排序toggle,可能是因为toggleGroup被隐藏了,手动将其激活后再获取即可。"); - else - toggleList = newToggleList; + if (_mappingDirty || ToggleListInvalid) + { + BakeToggleGroupItems(); + _mappingDirty = false; + } + + if (_noInit) + { + Initialize(); + _noInit = false; + } + + return toggleList; } } - #endregion - - #region 接口 /// /// 获取索引下的单选项组件 /// /// - public Toggle this[int index] => toggleList[index]; + public Toggle this[int index] => ToggleList[index]; - public int Count => toggleList.Count; + public int Count => ToggleList.Count; - public IEnumerator GetEnumerator() + /// + /// 直接获取缓存选中索引 + /// + public int CurrentSelectIndex => _nowSelectToggleIndex; + + /// + /// 选中项目实例 + /// + public Toggle CurrentSelectToggle => ToggleList[_nowSelectToggleIndex]; + + /// + /// 允许清空选项的选中状态 + /// + public bool AllowSwitchOff { - return toggleList.GetEnumerator(); + get => ToggleGroup.allowSwitchOff; + set => ToggleGroup.allowSwitchOff = value; } + + // 映射关系脏 + private bool _mappingDirty = false; - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } + // 未初始化 + private bool _noInit = true; + + // 当前选中的项目 + private int _nowSelectToggleIndex = -1; #endregion - #region 方法 + #region 结构更新 /// - /// 初始化 - /// - /// 自动将所有的按键绑定回调事件;如果作为刷新函数调用,请确保已经完全组索引。 - /// 或者可以直接清空旧项目(CleanToggle),然后逐个添加(AddToggle) - /// + /// 烘焙单选项组 /// + /// + /// 注意不要再这里面使用ToggleList + /// +#if ODIN_INSPECTOR + [HorizontalGroup("GetGroup"), Button("GetGroup")] +#endif + public virtual void BakeToggleGroupItems() + { + if (ToggleGroup == null) + { + if (ToggleListInvalid) + { + Debug.LogError("未指定单选项目组中的任何引用成员,无法初始化"); + return; + } + + var validToggle = toggleList.FirstOrDefault(a => a.group != null); + if (validToggle != null) + { + ToggleGroup = validToggle.group; + Debug.LogWarning("未指定单选项目组中的任何引用成员,但使用成员代偿"); + } + else + { + Debug.LogError("未指定单选项目组中的任何引用成员,且无法利用成员代偿"); + return; + } + } + + List tempToggleList = null; +#if UNITY_EDITOR + if (!Application.isPlaying) + { + if (!ToggleGroup.gameObject.activeInHierarchy) + { + var tempParents = ToggleGroup.transform.GetParents() + .Select(a => a.GetActivity()).ToList(); + ToggleGroup.gameObject.SetActivityInHierarchy(true); + tempToggleList = ToggleGroup.GetToggles(); + ToggleGroup.transform.GetParents() + .Zip(tempParents, (go, act) => (go, act)) + .ForEachDo(a => a.go.SetActivity(a.act)); + if (tempToggleList is not { Count: > 0 }) + Debug.LogError("无法获取ToggleGroup中的成员,可能由于toggleGroup被隐藏导致其无法初始化"); + } + else + tempToggleList = ToggleGroup.GetToggles(); + } + else +#endif + { + if (!ToggleGroup.gameObject.activeInHierarchy && ToggleListInvalid) + Debug.LogError( + $"当前运行状态导致无法直接获取ToggleGroup中的成员,且运行时我无法自行决定目标ToggleGroup({ToggleGroup.name})所属生命周期,请提前在编辑器中对相关状态进行烘焙"); + else + tempToggleList = ToggleGroup.GetToggles(); + } + // 需要注意的是,这里不能随意释放掉原来的选项列表 + if (tempToggleList is { Count: > 0 }) + toggleList = tempToggleList; + } +#if ODIN_INSPECTOR + [HorizontalGroup("GetGroup"), Button("GetGroup(Sort)")] +#endif + public void BakeSortToggelGroupItems() + { + BakeToggleGroupItems(); + if (ToggleListInvalid) + toggleList = MacroSort.FullCharacterOrderSort(toggleList, a => a.name) + .ToList(); + } +#if ODIN_INSPECTOR + [HorizontalGroup("GetGroup"), Button("GetGroup(Reverse Sort)")] +#endif + public void BakeReverseSortToggelGroupItems() + { + BakeToggleGroupItems(); + if (ToggleListInvalid) + toggleList = MacroSort.FullCharacterOrderSort(toggleList, a => a.name) + .Reverse() + .ToList(); + } +#if ODIN_INSPECTOR + [HorizontalGroup("GetGroup"), Button("SaveGroup")] +#endif + public void SetToggelGroupItems() + { + var realToggleGroup = ToggleGroup.GetToggles(); + if (ToggleListInvalid || toggleList.Count != realToggleGroup.Count) + { + Debug.LogError("编组无效,或编组成员与实际不符"); + return; + } + realToggleGroup.Clear(); + realToggleGroup.AddRange(toggleList); + Debug.Log("编组设置成功"); + } + public void Initialize() { - // 未指定组时,说明压根没用这部分功能,用不着初始化。 - if (ToggleGroup == null) + // 啥也没有,压根没用这部分功能,用不着初始化。 + if (ToggleGroup == null && toggleList.Count <= 0) return; - - // 防呆警告 + // 防呆 if (toggleList.Count <= 0) { var toggles = ToggleGroup.GetToggles(); @@ -243,26 +389,53 @@ namespace XericLibrary.Runtime.MacroLibrary toggleList = toggles; Debug.LogWarning($"在初始化单选项组时,{ToggleGroup.name}并未预先指定索引顺序,将默认使用大纲顺序。"); } + + if (toggles.Count <= 0) + { + Debug.LogWarning("在初始化单选项组时,目标单选项组为空"); + return; + } + } + + // 防空 + toggleList = toggleList.Where(a => a != null).ToList(); + + // 防傻 + if (ToggleGroup == null) + ToggleGroup = toggleList.FirstOrDefault(a => a.group != null)?.group; + if (ToggleGroup == null) + { + ToggleGroup = toggleList[0].transform.parent.gameObject.AddComponent(); + foreach (var toggle in toggleList) + toggle.group = ToggleGroup; } // 事件初始化 - for (int i = 0; i < toggleList.Count; i++) + for (var i = 0; i < toggleList.Count; i++) { var toggle = toggleList[i]; ToggleAddEvent(toggle); - if (toggle.isOn) - { - nowSelectToggleIndex = i; - nowSelectToggle = toggle; - } + if (_nowSelectToggleIndex < 0 && toggle.isOn) + _nowSelectToggleIndex = i; } - if (nowSelectToggle == null) - SetToggleOn(0); + // 如果不允许为空的情况下还为空,那就默认标记一个 + if (!ToggleGroup.allowSwitchOff && _nowSelectToggleIndex < 0) + SetToggleOnWithoutNotify(0); + + if (_noInit) + SetToggelGroupItems(); + + _mappingDirty = false; + _noInit = false; } + #endregion + + #region 初始化 和 增删改查 + /// /// 添加一个toggle /// @@ -272,27 +445,28 @@ namespace XericLibrary.Runtime.MacroLibrary { ToggleAddEvent(t); - var resultIndex = toggleList.Count; - toggleList.Add(t); + var resultIndex = ToggleList.Count; + ToggleList.Add(t); return resultIndex; } /// /// 移除一个toggle,这不会影响其他toggle的索引,但此处移除的位置会为空。 /// - /// 注 :这不会销毁toggle。 + /// 注意mapping管理的toggle在移除后会被清空事件 + /// 此举这不会销毁toggle。 /// /// /// /// 是否成功移除toggle public bool RemoveToggle(Toggle t) { - var index = toggleList.IndexOf(t); + var index = ToggleList.IndexOf(t); if (index < 0) return false; t.onValueChanged.RemoveAllListeners(); - toggleList[index] = null; + ToggleList[index] = null; return true; } @@ -302,14 +476,42 @@ namespace XericLibrary.Runtime.MacroLibrary /// 是否同时销毁所有toggle public void CleanToggle(bool allowDestroy) { - foreach (var t in toggleList) + foreach (var t in ToggleList) { t.onValueChanged.RemoveAllListeners(); if (allowDestroy) Object.Destroy(t); } - toggleList.Clear(); + ToggleList.Clear(); + } + + #endregion + + #region 事件流程 + + /// + /// 强制标记映射关系脏,在下次运行时将自动按需更新 + /// + public void SetDirty() + { + _mappingDirty = true; + } + + + /// + /// 查找当前选中实例在列表中的索引位置 + /// + public int CurrentSelectToggleIndex() + { + for (var i = 0; i < ToggleList.Count; i++) + { + if (!ToggleList[i].isOn) continue; + _nowSelectToggleIndex = i; + return _nowSelectToggleIndex; + } + + return -1; } @@ -319,25 +521,30 @@ namespace XericLibrary.Runtime.MacroLibrary /// private void ToggleAddEvent(Toggle t) { - t.onValueChanged.AddListener(a => + t.onValueChanged.RemoveListener(Listener); + t.onValueChanged.AddListener(Listener); + return; + + void Listener(bool b) { - if (a) ToggleRegister(t); - }); + if (b) ToggleRegister(t); + } } /// /// toggle注册的事件,只有当按下时才需要调用此事件。 /// /// - private void ToggleRegister(Toggle t) + protected virtual void ToggleRegister(Toggle t) { - nowSelectToggle = t; - nowSelectToggleIndex = GetIndex(t); + _nowSelectToggleIndex = GetIndex(t); OnAnyToggleSwitchOn?.Invoke(t); - OnAnyToggleIndexSwitchOn?.Invoke(nowSelectToggleIndex); + OnAnyToggleIndexSwitchOn?.Invoke(_nowSelectToggleIndex); } + + /// /// 获取toggle代表的索引 /// @@ -345,7 +552,17 @@ namespace XericLibrary.Runtime.MacroLibrary /// 如果这个toggle不存在于当前的单选项组中,返回-1 public int GetIndex(Toggle target) { - return toggleList.IndexOf(target); + if (target == null) + { + Debug.LogError("无法查询空toggle的索引"); + return 0; + } + + var index = ToggleList.IndexOf(target); + if (index >= 0) + return index; + Debug.LogError($"无法查询 {target.name} 在当前单选项组中的索引。"); + return 0; } /// @@ -356,10 +573,11 @@ namespace XericLibrary.Runtime.MacroLibrary /// public bool TryGetIndex(Toggle target, out int index) { - index = toggleList.IndexOf(target); + index = ToggleList.IndexOf(target); return index >= 0; } + /// /// 设置单选项激活 /// @@ -375,9 +593,9 @@ namespace XericLibrary.Runtime.MacroLibrary /// public void SetToggleOn(int index) { - if (0 < index && index < toggleList.Count) + if (0 <= index && index < ToggleList.Count) { - SetToggleOn(toggleList[index]); + SetToggleOn(ToggleList[index]); } } @@ -387,6 +605,7 @@ namespace XericLibrary.Runtime.MacroLibrary /// public void SetToggleOnWithoutNotify(Toggle target) { + _nowSelectToggleIndex = GetIndex(target); target.SetIsOnWithoutNotify(true); } @@ -396,9 +615,9 @@ namespace XericLibrary.Runtime.MacroLibrary /// public void SetToggleOnWithoutNotify(int index) { - if (0 < index && index < toggleList.Count) + if (0 < index && index < ToggleList.Count) { - SetToggleOnWithoutNotify(toggleList[index]); + SetToggleOnWithoutNotify(ToggleList[index]); } } @@ -409,21 +628,75 @@ namespace XericLibrary.Runtime.MacroLibrary public void Clear() { ToggleGroup.RemoveToggleGroupChangeEvent(); - toggleList.Clear(); + ToggleList.Clear(); } /// /// 清除映射结构,并销毁所有toggle组件 /// - public void RemoveAllToggle() + public void DestroyAllToggle() { - for (int i = toggleList.Count - 1; i >= 0; i--) + for (int i = ToggleList.Count - 1; i >= 0; i--) { - Object.Destroy(toggleList[i]); + Object.Destroy(ToggleList[i]); } Clear(); } + + + public IEnumerator GetEnumerator() + { + return ToggleList.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + #endregion + + #region 额外方法 + + public bool GetActive() => ToggleList.Any(a => a.gameObject.activeSelf); + + public bool GetActiveInHierarchy() => ToggleList.Any(a => a.gameObject.activeInHierarchy); + + public void SetActive(bool active) + { + ToggleGroup.gameObject.SetActivity(active); + ToggleList.ForEachDo(a => a.gameObject.SetActive(active)); + } + + public void SetActiveInHierarchy(bool active) + { + ToggleGroup.gameObject.SetActivity(active); + ToggleList.ForEachDo(a => a.gameObject.SetActivityInHierarchy(active)); + } + + #endregion + + #region 过时 + + /// + /// 清除映射结构,并销毁所有toggle组件 + /// + [Obsolete("方法命名不规范,改为使用DestroyAllToggle")] + public void RemoveAllToggle() + => DestroyAllToggle(); + + /// + /// 当前选中的toggle索引,依赖缓存,对于绕过该容器的单选项控制行为可能存在追踪不准确的问题。 + /// + [Obsolete("命名过时")] + public int NowSelectToggleIndex => CurrentSelectIndex; + + /// + /// 当前选中的toggle + /// + [Obsolete("命名规范过时")] + public Toggle NowSelectToggle => CurrentSelectToggle; #endregion } diff --git a/Runtime/UI/TmpText/TMPHyperlinkManager.cs b/Runtime/UI/TmpText/TMPHyperlinkManager.cs index 9732226..a01529d 100644 --- a/Runtime/UI/TmpText/TMPHyperlinkManager.cs +++ b/Runtime/UI/TmpText/TMPHyperlinkManager.cs @@ -209,7 +209,7 @@ namespace Deconstruction.UI.TmpText /// /// 强制刷新,如果刷新过一次,之后不论设定如何都将直接从缓存中返回对象,置位将跳过这个缓存 /// 强制给带有link标记的对象加上超链接组件 - /// 包括重复标记(也就是是否包含另一个超链接管理器作用域下的超链接对象) + /// 是否包含重复引用的链接(是否包含当前超链接管理器下其他超链接管理器作用域下的超链接对象) /// public List GetChildrenTmpText2Hyperlink( bool forceRefesh = false, @@ -255,5 +255,11 @@ namespace Deconstruction.UI.TmpText return result; } + +#if ODIN_INSPECTOR + [Button] +#endif + public void RefreshHyperLink() + => GetChildrenTmpText2Hyperlink(true); } } \ No newline at end of file diff --git a/Runtime/XericCecil.dll b/Runtime/XericCecil.dll index e37408a..25de67c 100644 Binary files a/Runtime/XericCecil.dll and b/Runtime/XericCecil.dll differ diff --git a/Runtime/XericCecil.pdb.meta b/Runtime/XericCecil.pdb.meta index 672049b..7e2643b 100644 --- a/Runtime/XericCecil.pdb.meta +++ b/Runtime/XericCecil.pdb.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 6872d3ed7dad0cd49b4e0f92ce6e95b1 +guid: 138831b823d56714db753f3bbfcca789 DefaultImporter: externalObjects: {} userData: diff --git a/Runtime/XericLibrary.dll b/Runtime/XericLibrary.dll index d732be0..eb0e84e 100644 Binary files a/Runtime/XericLibrary.dll and b/Runtime/XericLibrary.dll differ diff --git a/Runtime/XericLibrary.xml b/Runtime/XericLibrary.xml index bf385a3..3e1e0a2 100644 --- a/Runtime/XericLibrary.xml +++ b/Runtime/XericLibrary.xml @@ -3562,7 +3562,7 @@ - + Fisher-Yates洗牌算法,时间复杂度为O(n*n),空间复杂度为O(n); @@ -3658,7 +3658,7 @@ - + 返回值是无效的,因为这会立刻执行,这么做只是为了能插入到一些链式函数式中用作调试 @@ -3671,6 +3671,41 @@ 内插语法,表示此foreachdo不会作为执行器运行,而是作为其中一步执行 + 返回值可能是有效的,根据是否启用内插来判断 + + + + 使用链式语法进行foreach迭代,允许使用委托定义何时执行协作。 + + odin的库中也有一个ForEach,但如果关闭了Serializer模块的话,Sirenix.Utilities命名空间下的内容在编译时就不可用了。 + + + + + + 内插语法,表示此foreachdo不会作为执行器运行,而是作为其中一步执行 + 返回值可能是有效的,根据是否启用内插来判断 + + + + 使用链式语法进行foreach迭代,允许使用委托定义何时执行协作。 + + odin的库中也有一个ForEach,但如果关闭了Serializer模块的话,Sirenix.Utilities命名空间下的内容在编译时就不可用了。 + + + + + + 内插语法,表示此foreachdo不会作为执行器运行,而是作为其中一步执行 + 返回值可能是有效的,根据是否启用内插来判断 + + + + 重复对象 + + + + @@ -3780,6 +3815,81 @@ + + + 迭代直到计数超出 + + + + + + + + + 使用两个编组规则,实现一个带通过滤器 + 将给定数据根据条件A编组,然后根据条件B是否存在输出这个编组 + + + + 编组条件,只有连续为真的条件才是组 + 决定输出的条件 + + + + + 触发器编组。 + 当遇到触发器上升沿或下降沿时,执行一次编组 + + + + + 是上升沿,否则下降沿 + + + + + + 触发器编组。 + 当遇到触发器上升沿或下降沿时,执行一次编组 + + + + + 是上升沿,否则下降沿 + + + + + + 触发器编组。 + 当遇到触发器上升沿或下降沿时,执行一次编组 + + + + + 是上升沿,否则下降沿 + + + + + + 在连续的对象上计数 + + + + 如果对象为空,则根据枚举中第一个有效的项目进行选择 + 如果为真,则允许在默认值为空的情况下选择第一个不为空的对象作为判断依据 + + + + + 在连续为真的条件上计数 + + + + 计数条件 + + 在枚举器中定位到首个当equals结果为真的项目索引 @@ -4215,7 +4325,7 @@ 一个已经排好序的列表对象 查找的目标 返回索引是否为准确的 - 如果需要找到最接近的对象,则必须指定如何获取判断依据 + 如果需要找到最接近的对象,则必须指定如何获取判断依据 允许手动指定一个比较器,否则使用T类型默认的比较方式 在模糊判断时,选择更接近的一方,否则直接返回应当插入的位置 @@ -5186,6 +5296,22 @@ 使用循环累加验证小数步长的平方和 + + + 平方绝对值距离 + + + + + + + + 平方绝对值距离 + + + + + 获取圆上的点 @@ -7645,12 +7771,13 @@ - + - 设置组件的锚点为一个点 + 获取元素在屏幕上的绝对坐标 - - + 目标UI元素的RectTransform + 相对于元素 pivot 的偏移点(默认是元素中心点) + 屏幕绝对坐标(原点在屏幕左下角) @@ -7658,6 +7785,13 @@ + + + 获取世界绝对尺寸(递归向上计算尺寸) + + + + 变换顶点 @@ -7686,6 +7820,13 @@ + + + 设置组件的锚点为一个点 + + + + 在这个组件上截图 @@ -8830,6 +8971,19 @@ 排序算法库 + + + 选择排序,复杂度 O((n(n-2))/2) + 操作方式是从无序区选择数据插入到有序区的后面。(比较多,交换少,链表稳定) + + + 注意直接使用列表作为参数时,不要运行在多线程环境下。 + + + + + 返回从小到大的枚举器 + 选择排序,复杂度 O((n(n-2))/2) @@ -8840,6 +8994,19 @@ 返回从小到大的枚举器 + + + 快速排序,复杂度 O(n log2n) + 0 -> 最大值 n -> 最小值 + + + 注意直接使用列表作为参数时,不要运行在多线程环境下。 + + + + + + 快速排序,复杂度 O(n log2n) @@ -9387,10 +9554,10 @@ 文件句柄 + 异步的读取保存方法通常不需要等待,可以在末尾使用.ConfigureAwait(false),避免执行完毕后切换上下文,如果在ui线程中就不要调用这个了,其他情况下建议调用。 - @@ -10013,6 +10180,92 @@ + + + 获取对象自身有效性 + + + + + + + 获取对象世界有效性 + + + + + + + 获取对象在有限父级中的有效性 + + + + + + + + 设置对象有效性 + + + + + + + 设置对象有效性 + + + + + + + 设置对象有效性在有限的父级中 + + + + + + + 获取对象自身有效性 + + + + + + + 获取对象世界有效性 + + + + + + + 获取对象在有限父级中的有效性 + + + + + + + + 设置对象有效性 + + + + + + + 设置对象有效性 + + + + + + + 设置对象有效性在有限的父级中 + + + + 按顺序获取一个节点的所有父级节点 @@ -10020,6 +10273,13 @@ + + + 按顺序获取一个节点的所有父级节点 + + + + 按顺序获取一个节点的所有父级节点(安全模式:在遍历中操作循环体时,此处列表保持不变) @@ -10027,6 +10287,13 @@ + + + 按顺序获取一个节点的所有父级节点(安全模式:在遍历中操作循环体时,此处列表保持不变) + + + + 获取一个变换节点下所有的子成员(这个在unity中可以直接通过transform隐式转换) @@ -10034,6 +10301,13 @@ + + + 获取一个变换节点下所有的子成员(这个在unity中可以直接通过transform隐式转换) + + + + 获取一个变换节点下所有的子成员(安全模式:在遍历中操作循环体时,此处列表保持不变) @@ -10057,7 +10331,7 @@ - 递归获取一个变换节点下指定深度的子成员 + 深度优先地递归获取一个变换节点下指定深度内的子成员 递归深度,1表示仅在第一子集中寻找,2表示在包含下一级在内的所有成员中寻找 @@ -10097,13 +10371,21 @@ - + - 广度优先地获取一系列节点下的子成员 + 获取同级的兄弟节点 + + + 广度优先地获取跨多个父级的同级兄弟节点 + + + 查找的父级数量,1表示当前的父级,数量越高,查找的父级越高 + + 无论如何,获取这个组件,如果没有,就创建它 @@ -10136,6 +10418,14 @@ + + + 在兄弟节点中获取这个组件 + + + + + 在给定的集合中寻找一个组件 @@ -10172,6 +10462,32 @@ + + + 在给定的集合中寻找一个组件 + + + + + + + + + 在给定的集合中寻找一个组件 + + + + + + + + + 在兄弟节点中获取这个组件 + + + + + 将给定列表中的对象获取并转换为给定类的组件,返回的组件列表与原始列表一一对应 (这意味着其中包含无效的对象) @@ -10340,58 +10656,6 @@ 节点列表 执行的条件,为真时销毁 - - - 获取组件,如果组件为空则在节点中查找,如果还没有则创建这个组件 - - 要注意使用格式应当类似于这样: - rigidbody = rigidbody.GetIfComponent(this); - - - 组件类型 - 组件引用 - 要查找组件的位置 - - - - - 获取组件,如果组件为空则在节点中查找,如果还没有则创建这个组件 - - 要注意使用格式应当类似于这样: - rigidbody = rigidbody.GetIfComponent(this); - - - 组件类型 - 组件引用 - 要查找组件的位置 - - - - - 获取组件,如果组件为空则在节点中查找,如果还没有则创建这个组件 - - 要注意使用格式应当类似于这样: - rigidbody = rigidbody.GetIfComponent(this); - - - 组件类型 - 组件引用 - 要查找组件的位置 - - - - - 获取组件,如果组件为空则在节点中查找,如果还没有则创建这个组件 - - 要注意使用格式应当类似于这样: - rigidbody = rigidbody.GetIfComponent(this); - - - 组件类型 - 组件引用 - 要查找组件的位置 - - 加载宏 @@ -12755,7 +13019,7 @@ - 双胞胎哈希表 + 双生哈希表 @@ -14195,6 +14459,11 @@ 参数访问器 + + + unity委托耗时执行测试 + + 目录树型管理结构 @@ -14279,6 +14548,245 @@ 启用调试成员,将输出所有控制字符在遍历的成员 允许调试语句,将不再检查语句语法,可以完全使用路径语句进行流程遍历控制,而不会产生报错 + + + 大顶堆(一种排序算法),基于泛型List实现 + + + + + 添加元素 + + + 时间复杂度O(log n) + + + + + 移除顶部的元素并返回 + + + + 时间复杂度O(log n) + 如果堆为空,会抛出异常 + + + + + + + 移除指定索引处的元素并返回 + + + + 时间复杂度O(log n) + 索引越界会报错 + + + + + + + 移除指定的元素 + + + + 时间复杂度O(log n) + 返回是否移除成功,如果元素不在堆内就无法移除,返回false + + + + + + 查阅堆顶的元素 + + + 如果堆为空,会抛出异常 + + + + + + 清空堆 + + + + + 查询元素是否在堆内 + + + 时间复杂度O(n) + + + + + 查找元素在堆中首次出现的索引 + + + + 时间复杂度O(n) + 如果元素不存在,则返回-1 + + + + + + 从指定索引处向上堆化 + + + + + 从指定索引处向下堆化 + + + + + 交换两个索引位置的item + + + + + + + 返回指定节点的父节点的索引 + + + 如果已经到顶则仍然返回0 + + + + + 返回指定节点的左子结点的索引 + + + 如果不存在则返回-1 + + + + + 返回指定节点的右子结点的索引 + + + 如果不存在则返回-1 + + + + + 返回索引A处的元素是否比索引B处的大 + + + + + 灵活的八叉树实现,支持3D空间中的多种坐标类型 + + + 生成根节点时,可以适当扩大一点距离,如10%,可以避免加入时落在根节点边界上,减少插入时边界判断开销。 + ; + + + + 初始化八叉树 + + 八叉树边界 + 获取对象边界的函数 + 每个节点最大对象数 + 最大深度 + + + + 插入元素(修复:确保对象正确插入,处理边界检查) + + + + + 调试用:获取成功插入的对象总数 + + + + + 查找最近的元素(修复:处理无结果的情况,增加备选查找) + + + + + 获取对象的中心点 + + + + + 插入元素(修复:简化插入逻辑,确保对象正确进入节点) + + + + + 分裂节点(修复:确保对象正确迁移) + + + + + 在当前节点及其子节点中查找最近的元素 + + + + + 八叉树扩展方法,提供不同3D类型的边界转换 + + + + + 创建八叉树 + + 点列表 + 每个节点最大对象数 + 最大深度 + 八叉树 + + + + 计算点集的边界 + + 点列表 + 边界 + + + + 八叉树性能分析工具 + + + + + 分析八叉树性能 + + 八叉树 + 点列表 + 测试查询次数 + 性能统计 + + + + 分析树结构 + + + + + 估算内存使用 + + + + + 线性搜索 + + + + + 获取对象位置 + + + + + 格式化性能报告 + + 字典树节点类 @@ -14356,6 +14864,86 @@ + + + 灵活的四叉树实现,支持多种坐标类型 + + + + + 获取此四叉树的范围 + + + + + 初始化四叉树 + + 四叉树边界 + 获取对象边界的函数 + + + + 插入元素 + + + + + 查找范围内的元素 + + 查找范围 + 建议使用数据容器对象池控制,避免频繁GC,默认空将自动创建新的数据容器 + + + + + 查找最近的元素 + + + + + 调试绘制网格 + + + + + 插入元素 + + + + + 分裂为四个子节点 + + + + + 查找最近的元素 + + + + + 查找范围内的元素 + + + + + 绘制节点网格 + + + + + 判断两个矩形是否重叠 + + + + + 计算点到矩形的最小距离平方 + + + + + 四叉树扩展方法,提供不同类型的矩形转换 + + 全匿名成员 @@ -14480,7 +15068,7 @@ - 单例 + 杂项单例系统 @@ -15185,98 +15773,15 @@ - - - 一个简单的四叉树 - - 由于四叉树的特性,重新生成可能会比转置并平衡四叉树要简单和方便的多。 - 所以,如果需要维护四叉树,建议直接丢弃旧树重新生成 - - - - - - 插入元素 - - - - - - - - 寻找范围内的元素 - - - - - - - 四叉树节点 - - - - - 节点范围 - - - - - 节点内对象,为空代表此节点不包含成员 - - - - - 构造节点 - - 节点范围 - 节点层级 - - - - 元素插入 - - - - - - - - 执行细分,这会直接创建所有的子节点 - - - - - 查找给定范围象限 - - - - - - - 找回 - - - - - - - 四叉树识别接口 - - - - - 提供给四叉树容器可识别的范围 - - - 单例基础类,允许通过继承或直接注册的方式获取一个类的单例系统 - 如果给定的类通过继承的方式获得单例行为时,允许获取此单例类中的全部操作实现。 - 如果给定类通过类型限定语句注册到全局时,将不允许获取此单例中的操作实现。 + * 如果给定的类通过继承的方式获得单例行为时,允许获取此单例类中的全部操作实现。 + * 如果给定类通过类型限定语句注册到全局时,将不允许获取此单例中的操作实现。 + * 如果期望直接获得一个空的节点,可以使用transform作为泛型。 - 如果期望直接获得一个空的节点,可以使用transform作为泛型,毕竟所有节点都有这个组件。 + * 如果目标脚本无法继承自限定为自身的单例系统,可以使用旁系模式,使用超级单例包裹父类即可, @@ -15296,16 +15801,16 @@ 额外代理的单例 - - - 额外代理的单例 - - 组件自身单例(如果目标源并非自身,则可以使用自身引用获取) + + + 额外代理的单例 + + 具体的运行时定义实例 @@ -15350,38 +15855,72 @@ /// - 代理单例对象(世界父级优先) + 代理单例对象(代理优先,位于世界) 交叉同源对象,将另一个目标作为首选项覆盖原生,这在原型并非泛型限定时很有用。 - 注意: - 不允许:多线同步,异步执行,隐式声明,远程单例 - 允许:自身排斥,非运行时 + ## 警告: + * 多线异步 + 线程锁会阻止可能的多个实例的创建,并等待其他实例的获取完成。 + * 异步执行 + 线程锁会强制等待其他实例的获取完成 + * 非运行时 + 在编辑期间的操作是安全的,但编译操作刷新可能会引发实例重复,不建议实践 + ## 允许: + * 隐式声明 + 允许隐式,但注意调用时生命周期顺序,避免发生不必要的排斥 + * 自身排斥 + 自排时要求实例以最新实例为准 + * 远程单例 + 期望构建同质或劣质远程,如果实例已为远程,则返回远程,可能会影响场景切换时的生命周期顺序 /// - 代理单例对象(世界不销毁父级优先) + 代理单例对象(代理优先,位于持久世界) 交叉同源对象,将另一个目标作为首选项覆盖原生,这在原型并非泛型限定时很有用。 - 注意: - 不允许:多线同步,异步执行,隐式声明,远程单例 - 允许:自身排斥,非运行时 + ## 不允许: + * 非运行时 + 在编辑期间使用会引发错误 + ## 警告: + * 多线异步 + 线程锁会阻止可能的多个实例的创建,并等待其他实例的获取完成。 + * 异步执行 + 线程锁会强制等待其他实例的获取完成 + ## 允许: + * 隐式声明 + 允许隐式,但注意调用时生命周期顺序,避免发生不必要的排斥 + * 自身排斥 + 自排时要求实例以最新实例为准 + * 远程单例 + 期望构建优质远程,如果实例已为远程,则返回远程,可能会影响场景切换时的生命周期顺序 - 获取组件最近单例 + 常规单例(仅自身,位于世界) inst要求返回的对象必须为声明的泛型 (如果泛型类并非自己时无法获取自己的内容)。 如果目标已实现,但不存在于世界中时,将自动在当前场景中创建一个空节点用于存放对象。 - 注意: - 不允许:自身排斥,多线同步,异步执行,远程单例,非运行时 - 允许:隐式声明 + ## 警告: + * 多线异步 + 线程锁会阻止可能的多个实例的创建,并等待其他实例的获取完成。 + * 异步执行 + 线程锁会强制等待其他实例的获取完成 + * 自身排斥 + 自排时要求实例以最新实例为准 + * 非运行时 + 在编辑期间的操作是安全的,但编译等操作会导致实例不稳定(注意模式穿插可能导致混入意外实例) + ## 允许: + * 隐式声明 + 允许隐式,但注意调用时生命周期顺序,避免发生不必要的排斥 + * 远程单例 + 期望构建同质或劣质远程,如果实例已为远程,则返回远程,可能会影响场景切换时的生命周期顺序 @@ -15393,33 +15932,67 @@ 如果目标已实现,但不存在于世界中时,将自动在全局创建一个空节点用于存放自己。 如果泛型并非自己时,虽然可以定义,但无法在此处获取自己的内容,可以使用配合InstanceSelf使用。 - 注意: - 不允许:自身排斥,多线同步,非运行时 - 允许:异步执行,隐式声明,远程单例 + ## 不允许: + * 非运行时 + 在编辑期间使用会引发错误 + ## 警告: + * 多线异步 + 线程锁会阻止可能的多个实例的创建,并等待其他实例的获取完成。 + * 异步执行 + 线程锁会强制等待其他实例的获取完成 + * 自身排斥 + 自排时要求实例以最新实例为准 + ## 允许: + * 远程单例 + 如果实例已为远程,则返回远程,可能会影响场景切换时的生命周期顺序 + * 隐式声明 + 允许隐式,但注意调用时生命周期顺序,避免发生不必要的排斥 - 惰性单例(优先惰性单例) + 惰性单例(代理优先) 如果单例未声名,尝试查找,否则返回空 - 注意: - 不允许:隐式声明,远程单例,自身排斥 - 允许:多线同步,异步执行,非运行时 + ## 不允许: + * 非运行时 + 在编辑期间无法按预期执行,将退化为 Inst + * 隐式声明 + 除非对象另外使用隐式专用语法执行过至少一次,否则对象永远不会创建或被引用。 + ## 警告: + * 多线异步 + 线程锁会阻止可能的多个实例的创建,并等待其他实例的获取完成。 + * 异步执行 + 线程锁会强制等待其他实例的获取完成 + * 自身排斥 + 自排时要求实例以最新实例为准 + * 远程单例 + 不对远程设限,该单例不会对远程实例进行维护,不能保证有效性,除非这是你希望的 - 惰性单例(优先普通单例) + 惰性单例(完全惰性) - 如果单例未声名,尝试查找,否则返回空 + 如果单例未声名,返回空 - 注意: - 不允许:隐式声明,远程单例,自身排斥 - 允许:多线同步,异步执行,非运行时 + ## 不允许: + * 隐式声明 + 除非对象另外使用隐式专用语法执行过至少一次,否则对象永远不会创建或被引用。 + ## 警告: + * 多线异步 + 可以多线异步使用,但需要注意主线程生命周期 + * 异步执行 + 可以异步使用,但需要注意主线程生命周期 + * 自身排斥 + 是否唯一并不重要。 + * 远程单例 + 不对远程设限,该单例不会对远程实例进行维护,不能保证有效性,除非这是你希望的 + * 非运行时 + 可以引用到非运行时单例,但需要使用非运行时语法限定。 @@ -15427,12 +16000,23 @@ 获取此静态单例成员的绝对自身 - 功能与 GlobalInstance 一致,但: + 功能与 Inst 一致,但: 如果泛型并非自己时,虽然可以定义,但无法在此处获取泛型的内容。 - 注意: - 不允许:自身排斥,多线同步,非运行时 - 允许:异步执行,隐式声明,远程单例 + ## 警告: + * 多线异步 + 线程锁会阻止可能的多个实例的创建,并等待其他实例的获取完成。 + * 异步执行 + 线程锁会强制等待其他实例的获取完成 + * 非运行时 + 在编辑期间的操作是安全的,但编译操作刷新可能会引发实例重复,不建议实践 + ## 允许: + * 隐式声明 + 允许隐式,但注意调用时生命周期顺序,避免发生不必要的排斥 + * 自身排斥 + 自排时要求实例以最新实例为准 + * 远程单例 + 期望构建同质或劣质远程,如果实例已为远程,则返回远程,可能会影响场景切换时的生命周期顺序 @@ -15440,12 +16024,24 @@ 获取此静态单例成员的绝对自身 - 功能与 GlobalInstance 一致,但: + 功能与 GlobalInst 一致,但: 如果泛型并非自己时,虽然可以定义,但无法在此处获取泛型的内容。 - 注意: - 不允许:自身排斥,多线同步,非运行时 - 允许:异步执行,隐式声明,远程单例 + ## 不允许: + * 非运行时 + 在编辑期间使用会引发错误 + ## 警告: + * 多线异步 + 线程锁会阻止可能的多个实例的创建,并等待其他实例的获取完成。 + * 异步执行 + 线程锁会强制等待其他实例的获取完成 + ## 允许: + * 隐式声明 + 允许隐式,但注意调用时生命周期顺序,避免发生不必要的排斥 + * 自身排斥 + 自排时要求实例以最新实例为准 + * 远程单例 + 期望构建优质远程,如果实例已为远程,则返回远程,可能会影响场景切换时的生命周期顺序 @@ -15453,12 +16049,23 @@ 获取此静态单例成员的绝对自身 - 功能与 GlobalInstance 一致,但: + 功能与 Instance 一致,但: 如果泛型并非自己时,虽然可以定义,但无法在此处获取泛型的内容。 - 注意: - 不允许:自身排斥,多线同步,非运行时 - 允许:异步执行,隐式声明,远程单例 + ## 警告: + * 多线异步 + 线程锁会阻止可能的多个实例的创建,并等待其他实例的获取完成。 + * 异步执行 + 线程锁会强制等待其他实例的获取完成 + * 自身排斥 + 自排时要求实例以最新实例为准 + * 非运行时 + 在编辑期间的操作是安全的,但编译操作刷新可能会引发实例重复,不建议实践 + ## 允许: + * 隐式声明 + 允许隐式,但注意调用时生命周期顺序,避免发生不必要的排斥 + * 远程单例 + 期望构建同质或劣质远程,如果实例已为远程,则返回远程,可能会影响场景切换时的生命周期顺序 @@ -15469,9 +16076,21 @@ 功能与 GlobalInstance 一致,但: 如果泛型并非自己时,虽然可以定义,但无法在此处获取泛型的内容。 - 注意: - 不允许:自身排斥,多线同步,非运行时 - 允许:异步执行,隐式声明,远程单例 + ## 不允许: + * 非运行时 + 在编辑期间使用会引发错误 + ## 警告: + * 多线异步 + 线程锁会阻止可能的多个实例的创建,并等待其他实例的获取完成。 + * 异步执行 + 线程锁会强制等待其他实例的获取完成 + * 自身排斥 + 自排时要求实例以最新实例为准 + ## 允许: + * 远程单例 + 如果实例已为远程,则返回远程,可能会影响场景切换时的生命周期顺序 + * 隐式声明 + 允许隐式,但注意调用时生命周期顺序,避免发生不必要的排斥 @@ -15483,8 +16102,18 @@ 不建议依赖编辑时单例在状态与状态之间传递数据。 此单例对象不稳定且易变 如果现在不是编辑器模式,则与Instance一致 + + ## 不允许: + * 隐式声明 + * 多线异步 + * 异步执行 + * 非运行时 + * 远程单例 + * 自身排斥 + ## 警告: + ## 允许: 注意: - 不允许:多线同步,异步执行,远程单例,自身排斥 + 不允许:多线异步,异步执行,远程单例,自身排斥 允许:隐式声明,非运行时 @@ -15499,9 +16128,18 @@ 匿名单例需要手动维护,你可以调用 SyncCopyMainToAnonymous 或 SyncCopyAnonymousToMain 来在两个方向上同步。 匿名单例可以在单例被释放后仍然保存数据。 + ## 不允许: + * 隐式声明 + * 多线异步 + * 异步执行 + * 非运行时 + * 远程单例 + * 自身排斥 + ## 警告: + ## 允许: 注意: 不允许:隐式声明,远程单例,非运行时 - 允许:多线同步,异步执行,自身排斥 + 允许:多线异步,异步执行,自身排斥 @@ -15534,10 +16172,17 @@ - 检查泛型是否为当前类派生,也就是说这个是单例系统吗,还是旁例 + 检查泛型是否为当前类派生,也就是说是直系单例系统吗,否则旁系 + + + 插入编辑器转义 + + + + 基本单例组件中默认保留旧的成员,如果需要移除旧成员,请在base调用前调用DestroyInstanc() @@ -15554,6 +16199,16 @@ 移除此处的单例实例 + + + 移除已有的单例实例,以当前代理实例为准 + + + + + 移除当前代理实例,以首个单例实例为准 + + 手动指派一个实例到此 @@ -15695,23 +16350,12 @@ - - - 此处的矩形变换组件 - - 定义如何获取弱矩形变换组件,用于重载所有弱变换组件检查 - - - 定义如何获取弱变换组件,用于重载所有弱变换组件检查 - - - 定义如何获取此弱游戏对象, 用于重载所有弱游戏对象检查 @@ -15730,36 +16374,6 @@ - - - 定义此弱三维坐标,用于重载所有弱检查 - - - - - - 定义此弱三维旋转,用于重载所有弱检查 - - - - - - 定义此弱三维缩放,用于重载所有弱检查 - - - - - - 定义此弱界面三维坐标,用于重载所有弱检查 - - - - - - 定义此弱界面坐标,用于重载所有弱检查 - - - 如果目标为空 @@ -15973,6 +16587,11 @@ 烘焙循环平均距离 + + + 烘焙尺寸 + + 累计的总长度 @@ -16349,16 +16968,18 @@ - + - 找到最近点(快速二分法,要求曲线形状不能太复杂,否则很有可能陷入局部最优) + 找到最近点(线性查询,复杂度O(n)) - + - 比较两个参数内当前点的距离 + 找到最近点(八叉树查询,复杂度O(log n)) + + diff --git a/package.json b/package.json index fb5afb4..78deec3 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { "name": "com.lrss3.deconstruction", "displayName": "Xeric Library", - "version": "0.5.1", + "version": "0.5.3", "unity": "2021.3", - "description": "\u8fd9\u662f\u4e00\u4e2a\u89c4\u8303\u57fa\u7840\u7528\u4f8b\u7684\u6269\u5c55\u5e93, \u4e3b\u8981\u63d0\u4f9b\u4ee5\u4e0b\u529f\u80fd\r\n\r\n\u25aa\u7f16\u7a0b\u652f\u6301\uff1a\u51fd\u6570\u5e73\u6ed1\u3001 \u591a\u9879\u5f0f\u8ba1\u7b97\u3001 \u6743\u91cd\u62df\u5408\u3001 \u8fc7\u7a0b\u5206\u7ea7\u3001 \u5de5\u4e1a\u63a7\u5236\u3001 \u66f2\u7ebf\u7ed8\u5236\u3001 \u8def\u5f84\u8bbe\u7f6e\u3001 \u5bf9\u8c61\u63a7\u5236\u3001 \u8fed\u4ee3\u6269\u5c55\u3001 \u7a7a\u95f4\u53d8\u6362\u3001 \u72ec\u7279\u7ed3\u6784\u3001 \u6587\u672c\u683c\u5f0f\u3001 \u7c7b\u578b\u8f6c\u6362\u3001 \u673a\u5668\u7f16\u7801\u3001 \u5f00\u53d1\u8c03\u8bd5\u3001 \u52a8\u6001\u751f\u6210\u3001 \u51e0\u4f55\u521b\u5efa\u3001 \u5feb\u901f\u6c60\u5316\u3001 \u5bfc\u822a\u5bfb\u8def\u3001 \u9694\u79bb\u63a7\u5236\u3001 \u9694\u79bb\u8f93\u5165\u3001 \u8bed\u4e49\u5316\u59d4\u6258\u3001 \u53cd\u5c04\u8d85\u9a70\u3001 \u6570\u5b66\u5e38\u6570\u3001 \u5355\u4f4d\u6362\u7b97\u3001 \u6392\u5e8f\u7b97\u6cd5\u3001 \u7a0b\u5e8f\u8c03\u7528\u3001 \u7f51\u7edc\u8fde\u63a5\u7b49\u3002\r\n\u8fd8\u6709\u591a\u79cd\u7279\u6b8a\u7c7b\u578b, \u5305\u62ec\u4f46\u4e0d\u9650\u4e8e\uff1a\u591a\u7ef4\u5e03\u5c14\u3001 \u6837\u6761\u66f2\u7ebf\u3001 \u8d85\u7ea7\u5355\u4f8b\u3001 \u591a\u4f8b\u7cfb\u7edf\u3001 \u90bb\u5c45\u7f51\u7edc\u3001 \u56db\u53c9\u6811\u3001 \u5b57\u5178\u6811\u3001 \u8f6f\u5f15\u7528\u5c01\u88c5\u5668\u7b49\u3002\r\n\r\n\u25aa\u5e38\u7528\u811a\u672c\uff1a\u6e38\u620f\u4ea4\u4e92\u3001 \u754c\u9762\u9002\u914d\u3001 \u5f31\u6269\u5c55\u3001 \u7ed8\u5236\u5de5\u5382\u3001 SQL\u6269\u5c55\u3002\r\n\r\n\u25aa\u5f53\u524d\u63d2\u4ef6\u63d0\u4f9b\u7f16\u8f91\u5668\u529f\u80fd\uff1aDeepseek AI\u5bf9\u8bdd\u3002\r\n\u66f4\u591a\u7f16\u8f91\u5668\u529f\u80fd\u53c2\u8003\uff1a\r\n\u25aa\u5b89\u88c5Xeric Blueprint Graph\u4ee5\u83b7\u53d6Unity\u4e0a\u84dd\u56fe\u8282\u70b9\u529f\u80fd, \u5e76\u652f\u6301Xeric\u51fd\u6570\u5e93\u529f\u80fd\u3002\r\n\u25aa\u5b89\u88c5Xeric UI Graph\u4ee5\u83b7\u53d6\u84dd\u56fe\u5316UI\u751f\u6210\u529f\u80fd, \u4f7f\u7528\u84dd\u56fe\u903b\u8f91\u63a7\u5236UI\u4ea4\u4e92, \u751f\u6210\u903b\u8f91, \u5e76\u652f\u6301Xeric\u51fd\u6570\u5e93\u529f\u80fd\u3002\r\n\u25aa\u5b89\u88c5Digital Twin Tool\u4ee5\u83b7\u53d6\u5e38\u7528\u8c03\u8bd5\u5de5\u5177\u96c6\u3002\r\n\u25aa\u5b89\u88c5Nexus Frame Flow\u4ee5\u83b7\u53d6\u5de5\u4f5c\u67b6\u6784\u5904\u7406\u529f\u80fd\u3002\r\n\u25aa\u5b89\u88c5Xeric Editor\u8f85\u52a9\u5f15\u64ce\u5927\u7eb2\u7f8e\u5316\u7ec4\u4ef6\u3001 \u8d44\u6e90\u5783\u573e\u5904\u7406\u7ec4\u4ef6\u3001 \u8d44\u6e90\u7f13\u5b58\u7ec4\u4ef6\u3001 \u5feb\u901f\u622a\u56fe\u529f\u80fd, \u4ee5\u53ca\u66f4\u591a\u5feb\u6377\u952e\u529f\u80fd\r\n\r\n\u9700\u8981\u6ce8\u610f\uff1a\u63d2\u4ef6\u5185\u5982\u679c\u6d89\u53ca\u591a\u5e73\u53f0\u5207\u6362, \u53ef\u80fd\u4f1a\u63d0\u4f9b\u591a\u79cd\u81ea\u52a8\u6216\u624b\u52a8\u7684\u5207\u6362\u65b9\u6848, \u6216\u9ed8\u8ba4\u4f7f\u7528windows\u5e73\u53f0, \u8bf7\u6ce8\u610f\u8fa8\u522b\u3002\r\n\r\n\u5efa\u8bae\u6dfb\u52a0ODin\u63d2\u4ef6, \u4fbf\u4e8e\u5448\u73b0\u66f4\u591a\u754c\u9762\u529f\u80fd\u3002\r\n\r\n\u66f4\u591a\u8be6\u7ec6\u5185\u5bb9\u8bf4\u660e\u8bf7\u7ffb\u9605README\u6587\u6863\u3002\r\n\u5982\u679c\u53d1\u73b0\u4efb\u4f55\u95ee\u9898, \u5305\u62ec\u7248\u672c\u517c\u5bb9\u6027, \u8ba1\u7b97\u9519\u8bef, \u8c03\u7528\u9519\u8bef, \u4f7f\u7528\u95ee\u9898, \u90fd\u53ef\u4ee5\u901a\u8fc7\u53d1\u5e03\u9875Issues\u6216\u5176\u4ed6\u8054\u7cfb\u65b9\u5f0f\u627e\u6211\u83b7\u5f97\u5e2e\u52a9\u3002", + "description": "\u6b22\u8fce\u4f7f\u7528Xeric Library\uff0c\u8fd9\u662f\u4e00\u4e2a\u4e13\u6ce8\u4ee3\u7801\u7684\u6269\u5c55\u5e93\r\n\r\n\u25cf\u6269\u5c55Unity\u6210\u5458\u8bed\u6cd5\uff0c\u6269\u5c55\u6570\u636e\u7ed3\u6784Linq\u8bed\u6cd5\uff0c\u589e\u52a0\u8fd0\u7b97\u7b26\u8bed\u6cd5\uff0c\u652f\u6301\u5404\u7c7b\u9690\u5f0f\u7528\u6cd5\uff0c\u652f\u6301\u591a\u79cd\u8f6f\u5f15\u7528\u65b9\u6cd5\uff1b \u9488\u5bf9\u5927\u90e8\u5206\u4f7f\u7528\u573a\u666f\u52a0\u5165\u4e86\uff1a \u51fd\u6570\u5e73\u6ed1\u3001 \u591a\u9879\u5f0f\u8ba1\u7b97\u3001 \u6743\u91cd\u62df\u5408\u3001 \u8fc7\u7a0b\u5206\u7ea7\u3001 \u5de5\u4e1a\u63a7\u5236\u3001 \u66f2\u7ebf\u7ed8\u5236\u3001 \u8def\u5f84\u8bbe\u7f6e\u3001 \u5bf9\u8c61\u63a7\u5236\u3001 \u8fed\u4ee3\u6269\u5c55\u3001 \u7a7a\u95f4\u53d8\u6362\u3001 \u72ec\u7279\u7ed3\u6784\u3001 \u6587\u672c\u683c\u5f0f\u3001 \u7c7b\u578b\u8f6c\u6362\u3001 \u673a\u5668\u7f16\u7801\u3001 \u5f00\u53d1\u8c03\u8bd5\u3001 \u52a8\u6001\u751f\u6210\u3001 \u51e0\u4f55\u521b\u5efa\u3001 \u5feb\u901f\u6c60\u5316\u3001 \u5bfc\u822a\u5bfb\u8def\u3001 \u9694\u79bb\u63a7\u5236\u3001 \u9694\u79bb\u8f93\u5165\u3001 \u8bed\u4e49\u5316\u59d4\u6258\u3001 \u53cd\u5c04\u8d85\u9a70\u3001 \u6570\u5b66\u5e38\u6570\u3001 \u5355\u4f4d\u6362\u7b97\u3001 \u6392\u5e8f\u7b97\u6cd5\u3001 \u7a0b\u5e8f\u8c03\u7528\u3001 \u7f51\u7edc\u8fde\u63a5\u7b49\u5feb\u6377\u7528\u6cd5\u3002 \r\n\u25cf\u591a\u79cd\u7279\u6b8a\u7c7b\u578b\uff1a \u5305\u62ec\u4f46\u4e0d\u9650\u4e8e\uff1a\u591a\u7ef4\u5e03\u5c14\u3001 \u6837\u6761\u66f2\u7ebf\u3001 \u8d85\u7ea7\u5355\u4f8b\u3001 \u591a\u4f8b\u7cfb\u7edf\u3001 \u90bb\u5c45\u7f51\u7edc\u3001 \u56db\u53c9\u6811\u3001 \u5b57\u5178\u6811\u3001 \u8f6f\u5f15\u7528\u5c01\u88c5\u5668\u7b49\u3002 \r\n\u25cf\u5404\u79cd\u5e38\u7528\u811a\u672c\uff1a\u6e38\u620f\u4ea4\u4e92\u3001 \u754c\u9762\u9002\u914d\u3001 \u5f31\u6269\u5c55\u3001 \u7ed8\u5236\u5de5\u5382\u3001 SQL\u6269\u5c55\u3002\r\n\r\n\u25cf\u517c\u5bb9\u4e0d\u89c4\u8303\u7a0b\u5e8f\uff1a\u9488\u5bf9\u5404\u79cd\u4e0d\u89c4\u8303\u7684\uff0c\u6216\u6beb\u65e0\u8bbe\u8ba1\u89c4\u5219\u53ef\u8a00\u7684\u7a0b\u5e8f\uff0c\u63d0\u4f9b\u4e86\u66f4\u591a\u57fa\u4e8e\u53cd\u5c04\uff0cCIL\u7279\u6027\u7b49\u4f4e\u7ea7\u8bed\u6cd5\u7684\u7a0b\u5e8f\u6269\u5c55\uff0c\u5141\u8bb8\u901a\u8fc7\u5404\u79cd\u65b9\u5f0f\u5feb\u901f\u5b9e\u73b0\u76ee\u7684\uff1a\r\n1.\u811a\u672c\u6ca1\u6709\u7ee7\u627f\u5355\u4f8b\uff1f\u65e0\u6240\u8c13\uff0c\u8d85\u7ea7\u5355\u4f8b\u4e0d\u9700\u8981\u58f0\u540d\uff0c\u4e5f\u4e0d\u9700\u8981\u4fee\u6539\u4efb\u4f55\u811a\u672c\u5185\u5bb9\u5c31\u53ef\u4ee5\u5b9e\u73b0\u5355\u4f8b\u3002\r\n2.\u591a\u4e2a\u6570\u636e\u7ed3\u6784\u5b57\u6bb5\u4e4b\u95f4\u5197\u4f59\u91cd\u590d\uff1f\u65e0\u6240\u8c13\uff0c\u8f6f\u63a5\u53e3SoftInterface\u53ea\u9700\u8981\u4e00\u4e2a\u968f\u610f\u7684\u540d\u79f0\u5c31\u53ef\u4ee5\u83b7\u53d6\u548c\u8bbe\u7f6e\u503c\uff0c\u4f60\u53ef\u4ee5\u7528\u8f6f\u63a5\u53e3\u5728\u4efb\u610f\u5bf9\u8c61\u4e0a\u904d\u5386\u5b57\u6bb5\u5c5e\u6027\u7b49\u5185\u5bb9\u3002\r\n3.\u4e0d\u559c\u6b22\u5bf9\u8c61\u6c60\u7684\u521d\u59cb\u5316\uff1f\u6211\u4e5f\u662f\uff0cMacroPool.UnionSet \u8054\u5408\u5bf9\u8c61\u6c60\u652f\u6301\u5c06\u5fc5\u8981\u914d\u7f6e\u9879\u76ee\u6210\u5458\u5f00\u653e\u5230\u754c\u9762\u4e0a\uff0c\u7136\u540e\u76f4\u63a5\u8c03\u7528get\u5c31\u53ef\u4ee5\uff01\r\n4.\u7a0b\u5e8fUI\u6846\u67b6\u548c\u903b\u8f91\u6846\u67b6\u9ad8\u7ea7\u8026\u5408\u65e0\u4ece\u4e0b\u624b\uff1f\u6709\u70b9\u9ebb\u70e6\uff0c\u4e0d\u8fc7\u83dc\u5355\u7279\u6027\uff0c\u67e5\u627e\u7279\u6027\uff0c\u547d\u540d\u6807\u8bb0\u7279\u6027\u53ef\u4ee5\u5e2e\u52a9\u4f60\u65e0\u89c6\u5185\u5bb9\u67e5\u627e\u5b57\u6bb5\u5c5e\u6027\u65b9\u6cd5\u7c7b\u578b\u7b49\u5185\u5bb9\uff0c\u76f4\u63a5\u5c06\u7c7b\u4f20\u5165\u5c31\u80fd\u7a0b\u5e8f\u5316\u751f\u6210\u83dc\u5355\u754c\u9762\u3002\r\n5.\u6570\u636e\u7ed3\u6784\u592a\u591a\u5bfc\u81f4\u5728\u4ea4\u4e92\u65f6\u7a0b\u5e8f\u5361\u987f\uff1f\u8fd9\u662f\u4e2a\u95ee\u9898\uff0cXericUIActionVessel\u63d2\u4ef6\u4e2d\u63d0\u4f9b\u4e86\u591a\u79cd\u6570\u636e\u7ed3\u6784\u865a\u62df\u5316\u6280\u672f\uff0c\u57fa\u4e8e\u865a\u62df\u5316\u62c6\u5206\u5927\u91cf\u6570\u636e\u53ef\u4ee5\u51cf\u5c11\u538b\u529b\u3002\r\n6.\u559c\u6b22\u4f7f\u7528\u51fd\u6570\u5f0f\u548clinq\u8bed\u53e5\u7b80\u5316\u7a0b\u5e8f\uff1f\u6ca1\u6709\u95ee\u9898\uff01\u679a\u4e3e\u53ef\u4ee5\u4f7f\u7528MacroEnum\u5206\u7c7b\u548cMacroEnum\u6269\u5c55\uff1b\u6570\u5b66\uff0c\u5411\u91cf\uff0c\u51e0\u4f55\uff0c\u6570\u636e\u7ed3\u6784\u6269\u5c55\uff0c\u5e38\u89c1\u7b97\u6cd5\uff0c\u5e38\u7528\u5b57\u7b26\u8ba1\u7b97\u5df2\u7ecf\u5168\u90e8\u5185\u5d4cMacroMath\u5206\u7c7b\u4e2d\u3002\u8fd8\u6709\u66f4\u591a\u7b49\u4f60\u63a2\u7d22\uff01\r\n7.\u60f3\u4f7f\u7528\u66f4\u591a\u4e13\u7528\u6570\u636e\u7ed3\u6784\uff1f\u5927\u9876\u5806\uff0c\u56db\u53c9\u6811\uff0c\u516b\u53c9\u6811\uff0c\u5b57\u5178\u6811\uff0c\u65f6\u95f4\u6233\uff0c\u591a\u6bb5\u7ebf\uff0c\u8d1d\u585e\u5c14\uff0c\u591a\u7ef4\u5e03\u5c14\uff0c\u53cc\u751f\u54c8\u5e0c\u8868\uff0c\u76f8\u90bb\u7f51\u683c\u7b49\u7b49\u5185\u5bb9\u4efb\u541b\u4f7f\u7528\uff0c\u800c\u4e14\u8fd9\u4e9b\u6570\u636e\u7ed3\u6784\u90fd\u6709\u4e13\u7528\u7684\u754c\u9762\uff0c\u754c\u9762\u7f8e\u5316\u8fd9\u4e00\u5757\u3002\r\n8.\u60f3\u8981\u7acb\u523b\u80fd\u591f\u5728\u573a\u666f\u4e2d\u79fb\u52a8\u89d2\u8272\uff1f\u7b2c\u4e00\u4eba\u79f0\uff0c\u7b2c\u4e09\u4eba\u79f0\uff0c\u4e0a\u5e1d\u89c6\u89d2\u5df2\u7ecf\u51c6\u5907\u5c31\u7eea\uff01\r\n9.\u538c\u70e6\u590d\u6742\u7684\u6309\u952e\u68c0\u67e5\u903b\u8f91\uff1f\u6211\u5e2e\u4f60\uff01MacroKey\u4e2d\u7684\u6309\u952e\u72b6\u6001\u8868\u652f\u6301\u4ee5\u81ea\u5df1\u559c\u6b22\u7684\u72b6\u6001\u548c\u9891\u7387\u5904\u7406\u6309\u952e\uff0c\u5e76\u5904\u7406\u6210\u77ed\u6309\uff0c\u957f\u6309\uff0c\u53cc\u51fb\uff0c\u8fde\u51fb\uff0c\u62d6\u62fd\uff0c\u4ee5\u53ca\u8fd9\u4e9b\u72b6\u6001\u7684\u6309\u4e0b\u548c\u91ca\u653e\u72b6\u6001\uff01\u652f\u6301\u4ee5\u65f6\u95f4\uff0c\u5750\u6807\u7b49\u5171\u8ba14\u79cd\u6a21\u5f0f\u5904\u7406\u3002\r\n10.\u62c5\u5fc3\u517c\u5bb9\u6027\u5417\uff1f\u7a0b\u5e8f\u4e3b\u8981\u57fa\u4e8e2022\u7248\u672c\u5f00\u53d1\uff0c\u5411\u4e0b\u517c\u5bb92021\uff0c\u5411\u4e0a\u652f\u63016000\uff0c\u4e0d\u6d89\u53ca\u6e32\u67d3\u7ba1\u7ebfAPI\uff0c\u517c\u5bb9\u6027\u8f83\u597d\u3002\r\n\r\n\u25cf\u5f53\u524d\u63d2\u4ef6\u63d0\u4f9b\u7f16\u8f91\u5668\u529f\u80fd\uff1aDeepseek AI\u5bf9\u8bdd\u3002\r\n\u66f4\u591a\u7f16\u8f91\u5668\u529f\u80fd\u53c2\u8003\uff1a\r\n\u25cf\u5b89\u88c5Xeric Blueprint Graph\u4ee5\u83b7\u53d6Unity\u4e0a\u84dd\u56fe\u8282\u70b9\u529f\u80fd, \u5e76\u652f\u6301Xeric\u51fd\u6570\u5e93\u529f\u80fd\u3002\r\n\u25cf\u5b89\u88c5Xeric UI Graph\u4ee5\u83b7\u53d6\u84dd\u56fe\u5316UI\u751f\u6210\u529f\u80fd, \u4f7f\u7528\u84dd\u56fe\u903b\u8f91\u63a7\u5236UI\u4ea4\u4e92, \u751f\u6210\u903b\u8f91, \u5e76\u652f\u6301Xeric\u51fd\u6570\u5e93\u529f\u80fd\u3002\r\n\u25cf\u5b89\u88c5Digital Twin Tool\u4ee5\u83b7\u53d6\u5e38\u7528\u8c03\u8bd5\u5de5\u5177\u96c6\u3002\r\n\u25cf\u5b89\u88c5Nexus Frame Flow\u4ee5\u83b7\u53d6\u5de5\u4f5c\u67b6\u6784\u5904\u7406\u529f\u80fd\u3002\r\n\u25cf\u5b89\u88c5Xeric Editor\u8f85\u52a9\u5f15\u64ce\u5927\u7eb2\u7f8e\u5316\u7ec4\u4ef6\u3001 \u8d44\u6e90\u5783\u573e\u5904\u7406\u7ec4\u4ef6\u3001 \u8d44\u6e90\u7f13\u5b58\u7ec4\u4ef6\u3001 \u5feb\u901f\u622a\u56fe\u529f\u80fd, \u4ee5\u53ca\u66f4\u591a\u5feb\u6377\u952e\u529f\u80fd\r\n\r\n\u9700\u8981\u6ce8\u610f\uff1a\u63d2\u4ef6\u5185\u5982\u679c\u6d89\u53ca\u591a\u5e73\u53f0\u5207\u6362, \u53ef\u80fd\u4f1a\u63d0\u4f9b\u591a\u79cd\u81ea\u52a8\u6216\u624b\u52a8\u7684\u5207\u6362\u65b9\u6848, \u6216\u9ed8\u8ba4\u4f7f\u7528windows\u5e73\u53f0, \u8bf7\u6ce8\u610f\u8fa8\u522b\u3002\r\n\r\n\u5efa\u8bae\u6dfb\u52a0ODin\u63d2\u4ef6, \u4fbf\u4e8e\u5448\u73b0\u66f4\u591a\u754c\u9762\u529f\u80fd\u3002\r\n\r\n\u66f4\u591a\u8be6\u7ec6\u5185\u5bb9\u8bf4\u660e\u8bf7\u7ffb\u9605README\u6587\u6863\u3002\r\n\u5982\u679c\u53d1\u73b0\u4efb\u4f55\u95ee\u9898, \u5305\u62ec\u7248\u672c\u517c\u5bb9\u6027, \u8ba1\u7b97\u9519\u8bef, \u8c03\u7528\u9519\u8bef, \u4f7f\u7528\u95ee\u9898, \u90fd\u53ef\u4ee5\u901a\u8fc7\u53d1\u5e03\u9875Issues\u6216\u5176\u4ed6\u8054\u7cfb\u65b9\u5f0f\u627e\u6211\u83b7\u5f97\u5e2e\u52a9\u3002", "keywords": [ "unity", "xeric"