remove fsm
This commit is contained in:
parent
0d80bcfa5b
commit
152faa5991
@ -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<FsmDebuggerWindow>("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<int>();
|
||||
foreach (var kv in FSMDebugger.Entries) ids.Add(kv.Key);
|
||||
foreach (var id in ids) FSMDebugger.Unregister(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7e760f8a07d441dba01f9a5bf8fff62
|
||||
timeCreated: 1745562869
|
||||
@ -1,28 +0,0 @@
|
||||
using AlicizaX;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AlicizaX
|
||||
{
|
||||
/// <summary>
|
||||
/// 有限状态机组件。
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
[AddComponentMenu("Game Framework/FSM")]
|
||||
public sealed class FsmComponent : MonoBehaviour
|
||||
{
|
||||
private IFsmModule _mFsmModule = null;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_mFsmModule = ModuleSystem.RegisterModule<IFsmModule, FsmModule>();
|
||||
if (_mFsmModule == null)
|
||||
{
|
||||
Log.Error("FSM manager is invalid.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a69e41ab65d84e83a0468f1a2cc3926f
|
||||
timeCreated: 1712641057
|
||||
@ -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<IFsmRunner> _active = new List<IFsmRunner>(256);
|
||||
private readonly List<IFsmRunner> _toRemove = new List<IFsmRunner>(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<T> CreatePooled<T>(FsmConfig<T> cfg, T blackboard, UnityEngine.Object owner = null, Func<int, string> stateNameGetter = null)
|
||||
where T : class, IMemory
|
||||
{
|
||||
var fsm = Fsm<T>.Rent(cfg, blackboard, owner, stateNameGetter);
|
||||
_active.Add(fsm);
|
||||
return fsm;
|
||||
}
|
||||
|
||||
public void DestroyFsm<T>(Fsm<T> fsm) where T : class, IMemory
|
||||
{
|
||||
if (fsm == null) return;
|
||||
_toRemove.Add(fsm);
|
||||
}
|
||||
|
||||
public Fsm<T> Create<T>(FsmConfig<T> cfg, UnityEngine.Object owner = null, Func<int, string> stateNameGetter = null)
|
||||
where T : class, IMemory, new()
|
||||
{
|
||||
var bb = MemoryPool.Acquire<T>();
|
||||
var fsm = CreatePooled(cfg, bb, owner, stateNameGetter);
|
||||
return fsm;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9eb47e20b70b4505bc1ac91a2669c2db
|
||||
timeCreated: 1745559879
|
||||
@ -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>(T bb) where T : class, IMemory;
|
||||
|
||||
public delegate int StateUpdate<T>(T bb) where T : class, IMemory; // -1 = stay
|
||||
|
||||
public delegate void StateExit<T>(T bb) where T : class, IMemory;
|
||||
|
||||
public delegate bool Condition<T>(T bb) where T : class, IMemory;
|
||||
|
||||
// ===================== StateFunc =====================
|
||||
public sealed class StateFunc<T> where T : class, IMemory
|
||||
{
|
||||
public StateEnter<T> OnEnter;
|
||||
public StateUpdate<T> OnUpdate;
|
||||
public StateExit<T> OnExit;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static StateFunc<T> Make(StateEnter<T> enter = null, StateUpdate<T> update = null, StateExit<T> exit = null)
|
||||
{
|
||||
return new StateFunc<T>
|
||||
{
|
||||
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<T> where T : class, IMemory
|
||||
{
|
||||
public int From;
|
||||
public int To;
|
||||
public Condition<T> Cond; // may be null
|
||||
public int Priority; // smaller first
|
||||
public float Timeout; // >0 enables timeout
|
||||
|
||||
public Transition(int from, int to, Condition<T> 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<T> where T : class, IMemory
|
||||
{
|
||||
public readonly StateFunc<T>[] Funcs; // [state] -> funcs
|
||||
public readonly Transition<T>[] Transitions; // flat transitions list
|
||||
public readonly int StateCount; // >0
|
||||
public readonly int DefaultState; // initial state
|
||||
|
||||
public FsmConfig(StateFunc<T>[] func, Transition<T>[] 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<T> : IFsmRunner where T : class, IMemory
|
||||
{
|
||||
private static int _nextId;
|
||||
|
||||
public static Fsm<T> Rent(FsmConfig<T> cfg, T blackboard, UnityEngine.Object owner = null, Func<int, string> stateNameGetter = null)
|
||||
{
|
||||
Fsm<T> fsm = MemoryPool.Acquire<Fsm<T>>();
|
||||
fsm.Init(cfg, blackboard, owner, stateNameGetter);
|
||||
return fsm;
|
||||
}
|
||||
|
||||
public static void Return(Fsm<T> fsm)
|
||||
{
|
||||
if (fsm == null) return;
|
||||
MemoryPool.Release(fsm);
|
||||
}
|
||||
|
||||
// ---- Instance ----
|
||||
private StateFunc<T>[] _funcs;
|
||||
private Transition<T>[] _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<int, string> _stateNameGetter;
|
||||
|
||||
public T Blackboard
|
||||
{
|
||||
get => _bb;
|
||||
}
|
||||
|
||||
public Fsm()
|
||||
{
|
||||
}
|
||||
|
||||
private void Init(FsmConfig<T> cfg, T blackboard, UnityEngine.Object owner, Func<int, string> stateNameGetter)
|
||||
{
|
||||
Id = Interlocked.Increment(ref _nextId);
|
||||
DisplayName = typeof(T).Name;
|
||||
_funcs = cfg.Funcs;
|
||||
_trans = cfg.Transitions ?? Array.Empty<Transition<T>>();
|
||||
_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>[] 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<UnityEngine.Object> Owner; // may be null
|
||||
public Func<object> BlackboardGetter; // snapshot getter (only queried when painting)
|
||||
public Func<int, string> StateNameGetter; // may be null
|
||||
}
|
||||
|
||||
private static readonly Dictionary<int, Entry> _entries = new Dictionary<int, Entry>(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<int>.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<int>.Release(toRemove);
|
||||
}
|
||||
|
||||
internal static void Register<T>(in Fsm<T> 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<object> bbGetter, Func<int, string> stateNameGetter)
|
||||
{
|
||||
if (!_entries.TryGetValue(id, out var e))
|
||||
return;
|
||||
e.Owner = owner != null ? new WeakReference<UnityEngine.Object>(owner) : null;
|
||||
e.BlackboardGetter = bbGetter;
|
||||
e.StateNameGetter = stateNameGetter;
|
||||
}
|
||||
|
||||
internal static void Track<T>(in Fsm<T> 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<int, Entry> Entries => _entries;
|
||||
|
||||
// --- tiny List pool ---
|
||||
private static class ListPool<TItem>
|
||||
{
|
||||
private static readonly Stack<List<TItem>> _pool = new Stack<List<TItem>>(8);
|
||||
public static List<TItem> Get() => _pool.Count > 0 ? _pool.Pop() : new List<TItem>(16);
|
||||
|
||||
public static void Release(List<TItem> list)
|
||||
{
|
||||
list.Clear();
|
||||
_pool.Push(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e40b7705a0b45a3b1e46ad7e89a5ebd
|
||||
timeCreated: 1745547602
|
||||
@ -1,13 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AlicizaX
|
||||
{
|
||||
public interface IFsmModule : IModule, IModuleUpdate, IModuleAwake, IModuleLateUpdate
|
||||
{
|
||||
Fsm<T> Create<T>(FsmConfig<T> cfg, UnityEngine.Object owner = null, Func<int, string> stateNameGetter = null)
|
||||
where T : class, IMemory, new();
|
||||
|
||||
void DestroyFsm<T>(Fsm<T> fsm) where T : class, IMemory;
|
||||
}
|
||||
}
|
||||
@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5710f02ccd444b9c9c5d02d8bb2c3368
|
||||
Loading…
Reference in New Issue
Block a user