using Convention; using Convention.WindowsUI.Variant; using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using UnityEngine; using UnityEngine.InputSystem; namespace Demo.Game { public class RootObject : ScriptableObject { protected override bool IsSelfEnableUpdate => false; [Content] public Dictionary> UpdateChilds = new(); [Resources] public BasicAudioSystem audioSystem; [Content] public GameController RootGameController; [Setting]public string SourcePath; [Header("GlobalConfig")] public readonly HashSet LoadedScriptSet = new(); public readonly Dictionary LoadedScriptIndex = new(); public readonly Dictionary LoadedScriptRIndex = new(); private int LoadedScriptCnt = 0; /// /// 被用于自动生成 /// /// /// public int PushLoadedScriptObject(ScriptableObject obj) { while (LoadedScriptIndex.TryAdd(LoadedScriptCnt, obj) == false) LoadedScriptCnt++; LoadedScriptRIndex.Add(obj, LoadedScriptCnt); return LoadedScriptCnt++; } /// /// 被用于从缓存中生成 /// /// /// /// public int PushLoadedScriptObject(ScriptableObject obj, int index) { LoadedScriptIndex.Add(index, obj); LoadedScriptRIndex.Add(obj, index); return index; } /// /// 通过序列号获得物体 /// /// /// public ScriptableObject FindWithIndex(int index) { if(index<0) return null; return LoadedScriptIndex[index]; } /// /// 通过物体获得序列号 /// /// /// 若无法找到将返回-1 public int FindIndex(ScriptableObject obj) { return LoadedScriptRIndex.TryGetValue(obj, out var index) ? index : -1; } protected override IEnumerator DoSomethingDuringApplyScript() { yield return base.DoSomethingDuringApplyScript(); ScriptUpdate(RootGameController.SongOffset, 0.01f, TickType.Reset); if (RootGameController.IsMain) { Keyboard.current.onTextInput += InputCatchChar; } } public override IEnumerator UnloadScript() { if (RootGameController.IsMain) { Keyboard.current.onTextInput -= InputCatchChar; } yield return base.UnloadScript(); UpdateChilds.Clear(); } public void EnableScript(string sourcePath, GameController parent) { if (AllScriptableObjectCounterHierarchyItem == null) { AllScriptableObjectCounterHierarchyItem = HierarchyWindow.instance.CreateRootItemEntryWithBinders(typeof(ScriptableObject))[0]; } SourcePath = sourcePath; base.EnableScript(null); RootGameController = parent; } [Serializable] public struct InputCatchEntry { public float TimePoint; public Vector2 Position; public string InputKey; } /// /// 这个捕获列表大多数时候只构造一次,等同与, /// 但是会在中被父关卡加载后会被赋值,这是唯一的例外, /// 在多World项目中会由父世界的传递给其他加载进来的 /// public List InputCatch = new(); private void InputCatchChar(char ch) { if (RootGameController.IsAutoPlay) return; if (RootGameController.MainAudio.IsPlaying() == false) return; InputCatch.Add(new() { TimePoint = CurrentUpdateTickTimePoint, InputKey = ch.ToString(), Position = Mouse.current.position.ReadValue() }); } private float CurrentUpdateTickTimePoint; protected override void UpdateTicks(float currentTime, float deltaTime, TickType tickType) { if (RootGameController.IsMain) { void foo() { if (RootGameController.IsAutoPlay) return; if (RootGameController.MainAudio.IsPlaying() == false) return; // 更新缓存时间 CurrentUpdateTickTimePoint = currentTime; // 将距离当前更近的输入调整到更靠前的位置 InputCatch.Sort((x, y) => Mathf.Abs(x.TimePoint - currentTime).CompareTo(y.TimePoint - currentTime)); if (InputCatch.Count > 50) InputCatch = InputCatch.GetRange(0, 50); if (tickType == TickType.Start) { InputCatch.Clear(); } } foo(); } foreach (var (type, items) in UpdateChilds) { using (Profiler.BeginZone($"{type.Name}.ScriptUpdate")) foreach (var item in items) { try { item.ScriptUpdate(currentTime, deltaTime, tickType); } catch (Exception ex) { Debug.LogException(ex, item); } } } } } }