diff --git a/Editor/FSM/FsmDebuggerWindow.cs b/Editor/FSM/FsmDebuggerWindow.cs deleted file mode 100644 index af7a4b0..0000000 --- a/Editor/FSM/FsmDebuggerWindow.cs +++ /dev/null @@ -1,119 +0,0 @@ -using AlicizaX; -using UnityEditor; -using UnityEngine; - -internal class FsmDebuggerWindow : EditorWindow -{ - [MenuItem("Window/HighPerfFSM Debugger")] - public static void ShowWindow() - { - var win = GetWindow("FSM Debugger"); - win.Show(); - } - - private Vector2 _scroll; - private bool _autoRefresh = true; - - private void OnEnable() - { - FSMDebugger.SetEnabled(true); - EditorApplication.update += RepaintIfNeeded; - } - - private void OnDisable() - { - EditorApplication.update -= RepaintIfNeeded; - } - - private void RepaintIfNeeded() - { - if (_autoRefresh) Repaint(); - } - - private void OnGUI() - { - using (new EditorGUILayout.HorizontalScope(EditorStyles.toolbar)) - { - GUILayout.Label("HighPerfFSM Debugger", EditorStyles.boldLabel); - GUILayout.FlexibleSpace(); - _autoRefresh = GUILayout.Toggle(_autoRefresh, "Auto Refresh", EditorStyles.toolbarButton); - } - - _scroll = EditorGUILayout.BeginScrollView(_scroll); - - foreach (var kv in FSMDebugger.Entries) - { - var entry = kv.Value; - EditorGUILayout.BeginVertical("box"); - - using (new EditorGUILayout.HorizontalScope()) - { - GUILayout.Label($"ID: {entry.Id}", GUILayout.Width(90)); - GUILayout.Label(entry.Name, EditorStyles.boldLabel); - GUILayout.FlexibleSpace(); - } - - var stateName = (entry.StateNameGetter != null) - ? entry.StateNameGetter(entry.StateIndex) ?? entry.StateIndex.ToString() - : entry.StateIndex.ToString(); - - EditorGUILayout.LabelField("State", stateName); - EditorGUILayout.LabelField("TimeInState", entry.TimeInState.ToString("F3")); - - if (entry.BlackboardGetter != null && entry.Fields != null) - { - object bbObj = null; - try - { - bbObj = entry.BlackboardGetter(); - } - catch - { - } - - if (bbObj != null) - { - EditorGUILayout.LabelField("Blackboard"); - EditorGUI.indentLevel++; - for (int i = 0; i < entry.Fields.Length; i++) - { - var f = entry.Fields[i]; - object val = null; - try - { - val = f.GetValue(bbObj); - } - catch - { - } - - EditorGUILayout.LabelField(f.Name, val != null ? val.ToString() : "null"); - } - - EditorGUI.indentLevel--; - } - else - { - EditorGUILayout.HelpBox("Blackboard getter returned null.", MessageType.Info); - } - } - - if (entry.Owner != null && entry.Owner.TryGetTarget(out var owner) && owner != null) - { - EditorGUILayout.ObjectField("Owner", owner, typeof(UnityEngine.Object), true); - } - - EditorGUILayout.EndVertical(); - GUILayout.Space(4); - } - - EditorGUILayout.EndScrollView(); - - if (GUILayout.Button("Clear All (Unregister)")) - { - var ids = new System.Collections.Generic.List(); - foreach (var kv in FSMDebugger.Entries) ids.Add(kv.Key); - foreach (var id in ids) FSMDebugger.Unregister(id); - } - } -} diff --git a/Editor/FSM/FsmDebuggerWindow.cs.meta b/Editor/FSM/FsmDebuggerWindow.cs.meta deleted file mode 100644 index 4d6c854..0000000 --- a/Editor/FSM/FsmDebuggerWindow.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: b7e760f8a07d441dba01f9a5bf8fff62 -timeCreated: 1745562869 \ No newline at end of file diff --git a/Runtime/FSM/FsmComponent.cs b/Runtime/FSM/FsmComponent.cs deleted file mode 100644 index 206b3f3..0000000 --- a/Runtime/FSM/FsmComponent.cs +++ /dev/null @@ -1,28 +0,0 @@ -using AlicizaX; - -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace AlicizaX -{ - /// - /// 有限状态机组件。 - /// - [DisallowMultipleComponent] - [AddComponentMenu("Game Framework/FSM")] - public sealed class FsmComponent : MonoBehaviour - { - private IFsmModule _mFsmModule = null; - - private void Awake() - { - _mFsmModule = ModuleSystem.RegisterModule(); - if (_mFsmModule == null) - { - Log.Error("FSM manager is invalid."); - return; - } - } - } -} diff --git a/Runtime/FSM/FsmComponent.cs.meta b/Runtime/FSM/FsmComponent.cs.meta deleted file mode 100644 index f60b609..0000000 --- a/Runtime/FSM/FsmComponent.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: a69e41ab65d84e83a0468f1a2cc3926f -timeCreated: 1712641057 \ No newline at end of file diff --git a/Runtime/FSM/FsmModule.cs b/Runtime/FSM/FsmModule.cs deleted file mode 100644 index a80c774..0000000 --- a/Runtime/FSM/FsmModule.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; -using UnityEngine.Scripting; -using Object = UnityEngine.Object; - -namespace AlicizaX -{ - [Preserve] - internal sealed class FsmModule : IFsmModule - { - private readonly List _active = new List(256); - private readonly List _toRemove = new List(64); - - public int Priority => 0; - - void IModuleLateUpdate.LateUpdate() - { - RemoveFsm(); - } - - private void RemoveFsm() - { - if (_toRemove.Count > 0) - { - for (int i = 0; i < _toRemove.Count; i++) - { - var f = _toRemove[i]; - MemoryPool.Release(f); - f.Dispose(); - _active.Remove(f); - } - - _toRemove.Clear(); - } - } - - void IModuleUpdate.Update(float elapseSeconds, float realElapseSeconds) - { - float dt = Time.deltaTime; - for (int i = 0; i < _active.Count; i++) - { - _active[i].Tick(dt); - } - } - - void IModuleAwake.Awake() - { - } - - void IModule.Dispose() - { - for (int i = _active.Count - 1; _active.Count > 0; i--) - { - _toRemove.Add(_active[i]); - } - - RemoveFsm(); - } - - private Fsm CreatePooled(FsmConfig cfg, T blackboard, UnityEngine.Object owner = null, Func stateNameGetter = null) - where T : class, IMemory - { - var fsm = Fsm.Rent(cfg, blackboard, owner, stateNameGetter); - _active.Add(fsm); - return fsm; - } - - public void DestroyFsm(Fsm fsm) where T : class, IMemory - { - if (fsm == null) return; - _toRemove.Add(fsm); - } - - public Fsm Create(FsmConfig cfg, UnityEngine.Object owner = null, Func stateNameGetter = null) - where T : class, IMemory, new() - { - var bb = MemoryPool.Acquire(); - var fsm = CreatePooled(cfg, bb, owner, stateNameGetter); - return fsm; - } - } -} diff --git a/Runtime/FSM/FsmModule.cs.meta b/Runtime/FSM/FsmModule.cs.meta deleted file mode 100644 index dcc1530..0000000 --- a/Runtime/FSM/FsmModule.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 9eb47e20b70b4505bc1ac91a2669c2db -timeCreated: 1745559879 \ No newline at end of file diff --git a/Runtime/FSM/HighPerfFSM.cs b/Runtime/FSM/HighPerfFSM.cs deleted file mode 100644 index 5e972b2..0000000 --- a/Runtime/FSM/HighPerfFSM.cs +++ /dev/null @@ -1,414 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Threading; - -namespace AlicizaX -{ - internal interface IFsmRunner : IDisposable, IMemory - { - int Id { get; } - string DisplayName { get; } - UnityEngine.Object Owner { get; } - void Tick(float deltaTime); - } - - - public delegate void StateEnter(T bb) where T : class, IMemory; - - public delegate int StateUpdate(T bb) where T : class, IMemory; // -1 = stay - - public delegate void StateExit(T bb) where T : class, IMemory; - - public delegate bool Condition(T bb) where T : class, IMemory; - - // ===================== StateFunc ===================== - public sealed class StateFunc where T : class, IMemory - { - public StateEnter OnEnter; - public StateUpdate OnUpdate; - public StateExit OnExit; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static StateFunc Make(StateEnter enter = null, StateUpdate update = null, StateExit exit = null) - { - return new StateFunc - { - OnEnter = enter ?? EmptyEnter, - OnUpdate = update ?? Stay, - OnExit = exit ?? EmptyExit, - }; - } - - private static void EmptyEnter(T bb) - { - } - - private static int Stay(T bb) => -1; - - private static void EmptyExit(T bb) - { - } - } - - // ===================== Transition ===================== - public struct Transition where T : class, IMemory - { - public int From; - public int To; - public Condition Cond; // may be null - public int Priority; // smaller first - public float Timeout; // >0 enables timeout - - public Transition(int from, int to, Condition cond, int priority = 0, float timeout = 0f) - { - From = from; - To = to; - Cond = cond; - Priority = priority; - Timeout = timeout; - } - } - - internal struct TransitionIndex - { - public int Start; // start index in _trans - public int Length; // number of entries - } - - public readonly struct FsmConfig where T : class, IMemory - { - public readonly StateFunc[] Funcs; // [state] -> funcs - public readonly Transition[] Transitions; // flat transitions list - public readonly int StateCount; // >0 - public readonly int DefaultState; // initial state - - public FsmConfig(StateFunc[] func, Transition[] transition, int defaultState = -1) - { - Funcs = func; - Transitions = transition; - StateCount = Funcs.Length; - DefaultState = defaultState; - if (Funcs == null || Funcs.Length == 0) - throw new ArgumentException("Funcs must not be null/empty"); - if (StateCount <= 0) StateCount = Funcs.Length; - if ((uint)DefaultState >= (uint)StateCount) - throw new ArgumentOutOfRangeException(nameof(DefaultState)); - } - } - - public sealed class Fsm : IFsmRunner where T : class, IMemory - { - private static int _nextId; - - public static Fsm Rent(FsmConfig cfg, T blackboard, UnityEngine.Object owner = null, Func stateNameGetter = null) - { - Fsm fsm = MemoryPool.Acquire>(); - fsm.Init(cfg, blackboard, owner, stateNameGetter); - return fsm; - } - - public static void Return(Fsm fsm) - { - if (fsm == null) return; - MemoryPool.Release(fsm); - } - - // ---- Instance ---- - private StateFunc[] _funcs; - private Transition[] _trans; - private TransitionIndex[] _index; - private int _stateCount; - - private T _bb; - private bool _disposed; - - public int Id { get; private set; } - public string DisplayName { get; private set; } - public int Current { get; private set; } - public float TimeInState { get; private set; } - public bool Initialized { get; private set; } - public UnityEngine.Object Owner { get; private set; } - private Func _stateNameGetter; - - public T Blackboard - { - get => _bb; - } - - public Fsm() - { - } - - private void Init(FsmConfig cfg, T blackboard, UnityEngine.Object owner, Func stateNameGetter) - { - Id = Interlocked.Increment(ref _nextId); - DisplayName = typeof(T).Name; - _funcs = cfg.Funcs; - _trans = cfg.Transitions ?? Array.Empty>(); - _index = BuildIndex(_trans, cfg.StateCount); - _stateCount = cfg.StateCount; - - _bb = blackboard; - Owner = owner; - _stateNameGetter = stateNameGetter; - - Current = cfg.DefaultState; - TimeInState = 0f; - Initialized = false; - _disposed = false; - -#if UNITY_EDITOR - FSMDebugger.Register(this, typeof(T)); - FSMDebugger.BindProvider(Id, owner, BlackboardSnapshot, _stateNameGetter); -#endif - } - - private object BlackboardSnapshot() => _bb; - - private static TransitionIndex[] BuildIndex(Transition[] t, int stateCount) - { - if (t.Length > 1) - { - Array.Sort(t, (a, b) => - { - int f = a.From.CompareTo(b.From); - return (f != 0) ? f : a.Priority.CompareTo(b.Priority); - }); - } - - var idx = new TransitionIndex[stateCount]; - int cur = 0; - while (cur < t.Length) - { - int from = t[cur].From; - int end = cur + 1; - while (end < t.Length && t[end].From == from) end++; - if ((uint)from < (uint)stateCount) - { - idx[from].Start = cur; - idx[from].Length = end - cur; - } - - cur = end; - } - - return idx; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Reset(int state) - { - if (_disposed) return; - if ((uint)state >= (uint)_stateCount) return; - - if (Initialized) _funcs[Current].OnExit(_bb); - Current = state; - TimeInState = 0f; - _funcs[Current].OnEnter(_bb); - Initialized = true; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Tick(float deltaTime) - { - if (_disposed) return; - - bool flag = false; - if (!Initialized) - { - Reset(Current); - flag = true; - } - - if (!flag) - { - TimeInState += deltaTime; - - // 1) state internal update (may suggest next state) - int suggested = _funcs[Current].OnUpdate(_bb); - if (suggested >= 0 && suggested != Current) - { - ChangeState(suggested); - } - else - { - // 2) transitions (timeout first, then condition) - ref readonly TransitionIndex ti = ref _index[Current]; - for (int i = 0; i < ti.Length; i++) - { - ref readonly var tr = ref _trans[ti.Start + i]; - bool timeoutOk = (tr.Timeout > 0f && TimeInState >= tr.Timeout); - bool condOk = (!timeoutOk && tr.Cond != null && tr.Cond(_bb)); - if (timeoutOk || condOk) - { - ChangeState(tr.To); - break; - } - } - } - } - - -#if UNITY_EDITOR - if (FSMDebugger.Enabled) - FSMDebugger.Track(this); -#endif - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ChangeState(int next) - { - if ((uint)next >= (uint)_stateCount || next == Current) return; - _funcs[Current].OnExit(_bb); - Current = next; - TimeInState = 0f; - _funcs[Current].OnEnter(_bb); - } - - public void Dispose() - { - if (_disposed) return; - _disposed = true; -#if UNITY_EDITOR - FSMDebugger.Unregister(Id); -#endif - } - - - public void Clear() - { - _funcs = null; - _trans = null; - _index = null; - _stateCount = 0; - _stateNameGetter = null; - Owner = null; - Initialized = false; - TimeInState = 0f; - DisplayName = null; - MemoryPool.Release(_bb); - _bb = null; - } - } - -#if UNITY_EDITOR - // ===================== FSMDebugger (Editor Only) ===================== - public static class FSMDebugger - { - public sealed class Entry - { - public int Id; - public string Name; // Blackboard type name - public int StateIndex; - public double LastSeenEditorTime; - public float TimeInState; - public FieldInfo[] Fields; // cached fields of blackboard - public WeakReference Owner; // may be null - public Func BlackboardGetter; // snapshot getter (only queried when painting) - public Func StateNameGetter; // may be null - } - - private static readonly Dictionary _entries = new Dictionary(256); - - private const double PRUNE_INTERVAL_SEC = 3.0; - private const double STALE_SEC = 10.0; - private static double _lastPruneCheck; - public static bool Enabled { get; private set; } = true; - - static FSMDebugger() - { - UnityEditor.EditorApplication.update += PruneLoop; - } - - public static void SetEnabled(bool enabled) => Enabled = enabled; - - private static void PruneLoop() - { - double now = UnityEditor.EditorApplication.timeSinceStartup; - if (now - _lastPruneCheck < PRUNE_INTERVAL_SEC) return; - _lastPruneCheck = now; - - var toRemove = ListPool.Get(); - foreach (var kv in _entries) - { - var e = kv.Value; - bool deadOwner = false; - if (e.Owner != null && e.Owner.TryGetTarget(out var target)) - { - deadOwner = target == null; - } - else if (e.Owner != null) - { - deadOwner = true; - } - - bool stale = (now - e.LastSeenEditorTime) > STALE_SEC; - if (deadOwner || stale) - toRemove.Add(kv.Key); - } - - for (int i = 0; i < toRemove.Count; i++) - _entries.Remove(toRemove[i]); - - ListPool.Release(toRemove); - } - - internal static void Register(in Fsm fsm, Type blackboardType) where T : class, IMemory - { - var id = fsm.Id; - if (_entries.ContainsKey(id)) return; - - var fields = blackboardType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); - - _entries[id] = new Entry - { - Id = id, - Name = blackboardType.Name, - StateIndex = -1, - LastSeenEditorTime = UnityEditor.EditorApplication.timeSinceStartup, - TimeInState = 0f, - Fields = fields, - Owner = null, - BlackboardGetter = null, - StateNameGetter = null - }; - } - - internal static void BindProvider(int id, UnityEngine.Object owner, Func bbGetter, Func stateNameGetter) - { - if (!_entries.TryGetValue(id, out var e)) - return; - e.Owner = owner != null ? new WeakReference(owner) : null; - e.BlackboardGetter = bbGetter; - e.StateNameGetter = stateNameGetter; - } - - internal static void Track(in Fsm fsm) where T : class, IMemory - { - if (!_entries.TryGetValue(fsm.Id, out var e)) - return; - e.StateIndex = fsm.Current; - e.TimeInState = fsm.TimeInState; - e.LastSeenEditorTime = UnityEditor.EditorApplication.timeSinceStartup; - } - - public static void Unregister(int id) => _entries.Remove(id); - public static IReadOnlyDictionary Entries => _entries; - - // --- tiny List pool --- - private static class ListPool - { - private static readonly Stack> _pool = new Stack>(8); - public static List Get() => _pool.Count > 0 ? _pool.Pop() : new List(16); - - public static void Release(List list) - { - list.Clear(); - _pool.Push(list); - } - } - } -#endif -} diff --git a/Runtime/FSM/HighPerfFSM.cs.meta b/Runtime/FSM/HighPerfFSM.cs.meta deleted file mode 100644 index 066ea86..0000000 --- a/Runtime/FSM/HighPerfFSM.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 0e40b7705a0b45a3b1e46ad7e89a5ebd -timeCreated: 1745547602 \ No newline at end of file diff --git a/Runtime/FSM/IFsmModule.cs b/Runtime/FSM/IFsmModule.cs deleted file mode 100644 index 1c62a2b..0000000 --- a/Runtime/FSM/IFsmModule.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace AlicizaX -{ - public interface IFsmModule : IModule, IModuleUpdate, IModuleAwake, IModuleLateUpdate - { - Fsm Create(FsmConfig cfg, UnityEngine.Object owner = null, Func stateNameGetter = null) - where T : class, IMemory, new(); - - void DestroyFsm(Fsm fsm) where T : class, IMemory; - } -} diff --git a/Runtime/FSM/IFsmModule.cs.meta b/Runtime/FSM/IFsmModule.cs.meta deleted file mode 100644 index 9106f0e..0000000 --- a/Runtime/FSM/IFsmModule.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 5710f02ccd444b9c9c5d02d8bb2c3368 \ No newline at end of file