增加procedure模块
This commit is contained in:
parent
e31dda94ce
commit
958364080f
@ -1,6 +1,4 @@
|
||||
// ===================== FSMDebugger Window (unchanged API, auto-binding now) =====================
|
||||
|
||||
using AlicizaX.Fsm;
|
||||
using AlicizaX;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
using AlicizaX;
|
||||
using AlicizaX.Fsm;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AlicizaX.Fsm.Runtime
|
||||
namespace AlicizaX
|
||||
{
|
||||
/// <summary>
|
||||
/// 有限状态机组件。
|
||||
|
||||
@ -5,7 +5,7 @@ using UnityEngine;
|
||||
using UnityEngine.Scripting;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace AlicizaX.Fsm.Runtime
|
||||
namespace AlicizaX
|
||||
{
|
||||
[Preserve]
|
||||
internal sealed class FsmModule : IFsmModule
|
||||
|
||||
@ -4,7 +4,7 @@ using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace AlicizaX.Fsm
|
||||
namespace AlicizaX
|
||||
{
|
||||
internal interface IFsmRunner : IDisposable, IMemory
|
||||
{
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AlicizaX.Fsm.Runtime
|
||||
namespace AlicizaX
|
||||
{
|
||||
public interface IFsmModule : IModule, IModuleUpdate, IModuleAwake, IModuleLateUpdate
|
||||
{
|
||||
|
||||
@ -1,251 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using AlicizaX;
|
||||
|
||||
|
||||
public interface IState
|
||||
{
|
||||
IUltraFSM Fsm { get; set; }
|
||||
bool IsRegistered { get; set; }
|
||||
void Init();
|
||||
void Enter();
|
||||
void Exit();
|
||||
void Update(float deltaTime);
|
||||
void Destroy();
|
||||
}
|
||||
|
||||
public abstract class StateBase<TState> : IState where TState : Enum
|
||||
{
|
||||
public IUltraFSM Fsm { get; set; }
|
||||
public bool IsRegistered { get; set; }
|
||||
|
||||
protected virtual void OnInit()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void OnEnter()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void OnExit()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void OnUpdate(float deltaTime)
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void OnDestroy()
|
||||
{
|
||||
}
|
||||
|
||||
void IState.Init()
|
||||
{
|
||||
OnInit();
|
||||
}
|
||||
|
||||
void IState.Enter()
|
||||
{
|
||||
OnEnter();
|
||||
}
|
||||
|
||||
void IState.Exit()
|
||||
{
|
||||
OnExit();
|
||||
}
|
||||
|
||||
void IState.Update(float deltaTime)
|
||||
{
|
||||
OnUpdate(deltaTime);
|
||||
}
|
||||
|
||||
void IState.Destroy()
|
||||
{
|
||||
IsRegistered = false;
|
||||
OnDestroy();
|
||||
}
|
||||
|
||||
protected void SwitchState(TState newStateId)
|
||||
{
|
||||
(Fsm as SimpleFSM<TState>).SwitchState(newStateId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public interface IUltraFSM
|
||||
{
|
||||
string Name { get; }
|
||||
string StateName { get; }
|
||||
void Update(float deltaTime);
|
||||
void Dispose();
|
||||
}
|
||||
|
||||
public sealed class SimpleFSM<TState> : IUltraFSM where TState : Enum
|
||||
{
|
||||
private IState[] _states;
|
||||
private string _name;
|
||||
private int _currentIndex = -1;
|
||||
private int _registeredCount;
|
||||
private TState _currentState;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
}
|
||||
|
||||
|
||||
public string StateName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_currentIndex == -1)
|
||||
{
|
||||
return "None";
|
||||
}
|
||||
|
||||
return CurrentState.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public TState CurrentState
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_currentIndex == -1)
|
||||
throw new InvalidOperationException("No current state.");
|
||||
return _currentState;
|
||||
}
|
||||
}
|
||||
|
||||
public SimpleFSM()
|
||||
{
|
||||
Initialize("None", 16);
|
||||
}
|
||||
|
||||
internal int Capacity => _states?.Length ?? 0;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static int CalculateCapacity(int requested)
|
||||
{
|
||||
if (requested < 16) return 16;
|
||||
requested--;
|
||||
requested |= requested >> 1;
|
||||
requested |= requested >> 2;
|
||||
requested |= requested >> 4;
|
||||
requested |= requested >> 8;
|
||||
requested |= requested >> 16;
|
||||
return requested + 1;
|
||||
}
|
||||
|
||||
internal void Initialize(string name, int minCapacity)
|
||||
{
|
||||
_name = name;
|
||||
int newCapacity = CalculateCapacity(minCapacity);
|
||||
_states ??= new IState[newCapacity];
|
||||
}
|
||||
|
||||
private void Resize(int minCapacity)
|
||||
{
|
||||
int newCapacity = CalculateCapacity(minCapacity);
|
||||
if (_states != null && _states.Length >= newCapacity) return;
|
||||
Array.Resize(ref _states, newCapacity);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Register<T>(TState stateId) where T : class, IState, new()
|
||||
{
|
||||
int stateIdValue = Convert.ToInt32(stateId);
|
||||
if (stateIdValue < 0)
|
||||
throw new ArgumentException("State ID must be non-negative.");
|
||||
|
||||
if (stateIdValue >= _states.Length)
|
||||
Resize(stateIdValue + 1);
|
||||
|
||||
// 检查当前状态是否已注册,若存在则先释放
|
||||
var existingState = _states[stateIdValue];
|
||||
if (existingState != null && existingState.IsRegistered)
|
||||
{
|
||||
existingState.Destroy();
|
||||
_registeredCount--;
|
||||
}
|
||||
|
||||
IState state = default;
|
||||
state = new T();
|
||||
|
||||
_states[stateIdValue] = state;
|
||||
|
||||
if (!state.IsRegistered)
|
||||
{
|
||||
state.Fsm = this;
|
||||
state.Init();
|
||||
state.IsRegistered = true;
|
||||
_registeredCount++;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void SwitchState(TState newStateId)
|
||||
{
|
||||
int newStateIdValue = Convert.ToInt32(newStateId);
|
||||
if (newStateIdValue < 0 || newStateIdValue >= _states.Length)
|
||||
throw new ArgumentOutOfRangeException(nameof(newStateId), "State ID is out of range.");
|
||||
int prevIndex = _currentIndex;
|
||||
int newIndex = newStateIdValue;
|
||||
|
||||
if (prevIndex == newIndex) return;
|
||||
|
||||
ExitState(prevIndex);
|
||||
EnterState(newIndex);
|
||||
_currentIndex = newIndex;
|
||||
_currentState = newStateId;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
if ((uint)_currentIndex < (uint)_states.Length)
|
||||
_states[_currentIndex]?.Update(deltaTime);
|
||||
}
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void ExitState(int index)
|
||||
{
|
||||
if ((uint)index < (uint)_states.Length)
|
||||
_states[index]?.Exit();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void EnterState(int index)
|
||||
{
|
||||
if ((uint)index < (uint)_states.Length)
|
||||
{
|
||||
IState state = _states[index];
|
||||
if (state.IsRegistered)
|
||||
state.Enter();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_states == null) return;
|
||||
|
||||
for (int i = 0; i < _states.Length; i++)
|
||||
{
|
||||
IState state = _states[i];
|
||||
if (state != null && state.IsRegistered)
|
||||
{
|
||||
state.Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
// 清空数组引用,帮助 GC 回收内存
|
||||
Array.Clear(_states, 0, _states.Length);
|
||||
_states = null;
|
||||
|
||||
_currentIndex = -1;
|
||||
_registeredCount = 0;
|
||||
}
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 064e59389d6a4e61816e12e5de6848ed
|
||||
timeCreated: 1756985353
|
||||
3
Runtime/Procedure.meta
Normal file
3
Runtime/Procedure.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 131e0fd9dfe2470394ebf46fd2a9c781
|
||||
timeCreated: 1763450210
|
||||
13
Runtime/Procedure/IProcedureModule.cs
Normal file
13
Runtime/Procedure/IProcedureModule.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AlicizaX
|
||||
{
|
||||
public interface IProcedureModule:IModule,IModuleUpdate
|
||||
{
|
||||
void InitializeProcedure(List<IProcedure> availableProcedures, Type defaultProcedureType);
|
||||
void ClearAllProcedures();
|
||||
bool SwitchProcedure<T>() where T : IProcedure;
|
||||
bool SwitchProcedure(Type procedureType);
|
||||
}
|
||||
}
|
||||
3
Runtime/Procedure/IProcedureModule.cs.meta
Normal file
3
Runtime/Procedure/IProcedureModule.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18d5ca3d17384612b2d2023084b6a97b
|
||||
timeCreated: 1763451617
|
||||
72
Runtime/Procedure/ProcedureBase.cs
Normal file
72
Runtime/Procedure/ProcedureBase.cs
Normal file
@ -0,0 +1,72 @@
|
||||
namespace AlicizaX
|
||||
{
|
||||
public interface IProcedure
|
||||
{
|
||||
IProcedureModule ProcedureModule { get; set; }
|
||||
void Init();
|
||||
void Enter();
|
||||
void Leave();
|
||||
void Update();
|
||||
void Destroy();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 流程基类 - 使用模板方法模式定义流程生命周期
|
||||
/// </summary>
|
||||
public abstract class ProcedureBase : IProcedure
|
||||
{
|
||||
public IProcedureModule ProcedureModule { get; set; }
|
||||
|
||||
void IProcedure.Init()
|
||||
{
|
||||
OnInit();
|
||||
}
|
||||
|
||||
void IProcedure.Enter()
|
||||
{
|
||||
OnEnter();
|
||||
}
|
||||
|
||||
void IProcedure.Leave()
|
||||
{
|
||||
OnLeave();
|
||||
}
|
||||
|
||||
void IProcedure.Update()
|
||||
{
|
||||
OnUpdate();
|
||||
}
|
||||
|
||||
void IProcedure.Destroy()
|
||||
{
|
||||
OnDestroy();
|
||||
}
|
||||
|
||||
|
||||
protected virtual void OnInit()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void OnEnter()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void OnLeave()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void OnUpdate()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void OnDestroy()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
protected internal void SwitchProcedure<T>() where T : ProcedureBase
|
||||
{
|
||||
ProcedureModule.SwitchProcedure<T>();
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Runtime/Procedure/ProcedureBase.cs.meta
Normal file
3
Runtime/Procedure/ProcedureBase.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 367e3373495c49da9c1d85e9c5a68bf3
|
||||
timeCreated: 1763450223
|
||||
21
Runtime/Procedure/ProcedureComponent.cs
Normal file
21
Runtime/Procedure/ProcedureComponent.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace AlicizaX
|
||||
{
|
||||
[DisallowMultipleComponent]
|
||||
[AddComponentMenu("Game Framework/Procedure")]
|
||||
public sealed class ProcedureComponent : MonoBehaviour
|
||||
{
|
||||
private IProcedureModule _mProcedureModule = null;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_mProcedureModule = ModuleSystem.RegisterModule<IProcedureModule, ProcedureModule>();
|
||||
if (_mProcedureModule == null)
|
||||
{
|
||||
Log.Error("Procedure Module is invalid.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Runtime/Procedure/ProcedureComponent.cs.meta
Normal file
3
Runtime/Procedure/ProcedureComponent.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c0a419f3af614cdda5267671f803dfdb
|
||||
timeCreated: 1763451994
|
||||
132
Runtime/Procedure/ProcedureModule.cs
Normal file
132
Runtime/Procedure/ProcedureModule.cs
Normal file
@ -0,0 +1,132 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AlicizaX
|
||||
{
|
||||
internal class ProcedureModule : IProcedureModule
|
||||
{
|
||||
private readonly Dictionary<Type, IProcedure> _procedures = new Dictionary<Type, IProcedure>();
|
||||
private IProcedure _currentProcedure;
|
||||
private IProcedure _defaultProcedure;
|
||||
|
||||
|
||||
public void InitializeProcedure(List<IProcedure> availableProcedures, Type defaultProcedureType)
|
||||
{
|
||||
_procedures.Clear();
|
||||
foreach (var procedure in availableProcedures)
|
||||
{
|
||||
var type = procedure.GetType();
|
||||
_procedures[type] = procedure;
|
||||
procedure.ProcedureModule = this;
|
||||
procedure.Init();
|
||||
}
|
||||
|
||||
if (_procedures.ContainsKey(defaultProcedureType))
|
||||
{
|
||||
_defaultProcedure = _procedures[defaultProcedureType];
|
||||
SwitchProcedure(defaultProcedureType);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Info($"默认流程 {defaultProcedureType.Name} 未注册!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// 清除所有流程
|
||||
/// </summary>
|
||||
public void ClearAllProcedures()
|
||||
{
|
||||
if (_procedures != null)
|
||||
{
|
||||
foreach (var procedure in _procedures.Values)
|
||||
{
|
||||
procedure.Destroy();
|
||||
}
|
||||
|
||||
_procedures.Clear();
|
||||
}
|
||||
|
||||
_currentProcedure = null;
|
||||
_defaultProcedure = null;
|
||||
}
|
||||
|
||||
public bool SwitchProcedure<T>() where T : IProcedure
|
||||
{
|
||||
if (HasProcedure<T>())
|
||||
{
|
||||
return SwitchProcedure(typeof(T));
|
||||
}
|
||||
|
||||
if (_defaultProcedure != null)
|
||||
{
|
||||
Debug.LogWarning($"流程 {typeof(T).Name} 不存在,切换到默认流程");
|
||||
return SwitchToDefault();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public bool SwitchProcedure(Type procedureType)
|
||||
{
|
||||
var nextProcedure = _procedures[procedureType];
|
||||
var lastProcedure = _currentProcedure;
|
||||
|
||||
if (lastProcedure == nextProcedure)
|
||||
return true;
|
||||
|
||||
if (lastProcedure != null)
|
||||
{
|
||||
lastProcedure.Leave();
|
||||
}
|
||||
|
||||
nextProcedure.Enter();
|
||||
_currentProcedure = nextProcedure;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 切换到默认流程
|
||||
/// </summary>
|
||||
private bool SwitchToDefault()
|
||||
{
|
||||
if (_defaultProcedure != null)
|
||||
{
|
||||
return SwitchProcedure(_defaultProcedure.GetType());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否存在指定类型的流程
|
||||
/// </summary>
|
||||
private bool HasProcedure<T>() where T : IProcedure
|
||||
{
|
||||
return _procedures.ContainsKey(typeof(T));
|
||||
}
|
||||
|
||||
|
||||
void IModule.Dispose()
|
||||
{
|
||||
ClearAllProcedures();
|
||||
}
|
||||
|
||||
public int Priority { get; }
|
||||
|
||||
void IModuleUpdate.Update(float elapseSeconds, float realElapseSeconds)
|
||||
{
|
||||
if (_currentProcedure != null)
|
||||
{
|
||||
_currentProcedure.Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Runtime/Procedure/ProcedureModule.cs.meta
Normal file
3
Runtime/Procedure/ProcedureModule.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4272c5c31b6b4a459f1da37a228cfd3f
|
||||
timeCreated: 1763450372
|
||||
Loading…
Reference in New Issue
Block a user