From 93531fdabfb2a7dd278a646b16a2ba86f2c45f48 Mon Sep 17 00:00:00 2001 From: Han <1985708279@qq.com> Date: Fri, 21 Mar 2025 18:34:26 +0800 Subject: [PATCH] FSM_Over --- .../RunTime/FSMController.cs | 132 ++++++++++++++++ .../RunTime/FSMController.cs.meta | 11 ++ .../RunTime/FSMInitialize.cs | 46 ++++++ .../RunTime/FSMInitialize.cs.meta | 11 ++ .../RunTime/FSMManager.cs | 146 ++++++++++++++++++ .../RunTime/FSMManager.cs.meta | 11 ++ .../03.FiniteStateMachine/RunTime/IState.cs | 84 ++++++++++ .../RunTime/IState.cs.meta | 11 ++ .../RunTime/PlayerFSMExample.cs | 53 +++++++ .../RunTime/PlayerFSMExample.cs.meta | 11 ++ 10 files changed, 516 insertions(+) create mode 100644 Assets/03.FiniteStateMachine/RunTime/FSMController.cs create mode 100644 Assets/03.FiniteStateMachine/RunTime/FSMController.cs.meta create mode 100644 Assets/03.FiniteStateMachine/RunTime/FSMInitialize.cs create mode 100644 Assets/03.FiniteStateMachine/RunTime/FSMInitialize.cs.meta create mode 100644 Assets/03.FiniteStateMachine/RunTime/FSMManager.cs create mode 100644 Assets/03.FiniteStateMachine/RunTime/FSMManager.cs.meta create mode 100644 Assets/03.FiniteStateMachine/RunTime/IState.cs create mode 100644 Assets/03.FiniteStateMachine/RunTime/IState.cs.meta create mode 100644 Assets/03.FiniteStateMachine/RunTime/PlayerFSMExample.cs create mode 100644 Assets/03.FiniteStateMachine/RunTime/PlayerFSMExample.cs.meta diff --git a/Assets/03.FiniteStateMachine/RunTime/FSMController.cs b/Assets/03.FiniteStateMachine/RunTime/FSMController.cs new file mode 100644 index 0000000..9848406 --- /dev/null +++ b/Assets/03.FiniteStateMachine/RunTime/FSMController.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +public class FSMController : MonoBehaviour +{ + private Dictionary states = new Dictionary(); + + public void AddState(SingleState state) + { + var type = state.GetType(); + if (!states.ContainsKey(type)) + { + // 添加时初始化 + state.Machine = this; + state.OnInit(); + states.Add(type, state); + } + else + { + Debug.LogError("该FSMController中已经添加过该状态!!!"); + } + } + +/* //public bool IsRunning() where T : SingleState => IsRunning(typeof(T)); + + //public void Enter() where T : SingleState => Enter(typeof(T)); + + //public void Exit() where T : SingleState => Exit(typeof(T)); + + //public void ForceEnter() where T : SingleState => ForceEnter(typeof(T));*/ + + public bool IsRunning(Type type) + { + if (states.ContainsKey(type)) + { + if (states[type].IsRunning) return true; + } + else + { + Debug.LogError("状态已不存在!!!"); + } + return false; + } + + public void Enter(Type type) + { + if (states.ContainsKey(type)) + { + if (IsRunning(type)) + { + Debug.LogError("该状态正在进行,无法再次进入!!!"); + return; + } + ForceEnter(type); + } + else + { + Debug.LogError("状态已不存在!!!"); + } + + } + + public void ForceEnter(Type type) + { + if (states.ContainsKey(type)) + { + SingleState state = states[type]; + state.OnEnter(); + state.IsRunning = true; + } + else + { + Debug.LogError("状态已不存在!!!"); + } + } + + public void Exit(Type type) + { + if (states.TryGetValue(type, out SingleState state)) + { + if (!IsRunning(type)) return; + state.IsRunning = false; + state.OnExit(); + } + else + { + Debug.LogError("状态已不存在!!!"); + } + + } + + public void ExitAll() + { + foreach (var state in states) + { + if (state.Value.IsRunning) Exit(state.Key); + } + } + + private void Update() + { + foreach (var state in states) + { + if (state.Value.IsRunning) state.Value.Update(); + } + } + + private void FixedUpdate() + { + foreach (var state in states) + { + if (state.Value.IsRunning) state.Value.FixedUpdate(); + } + } + + private void OnDestroy() + { + ExitAll(); + // 遍历字典中的每个状态 + foreach (var key in states.Keys.ToList()) + { + states[key].OnDestory(); + // 将每个值设置为 null,释放引用 + states[key] = null; + } + // 清空字典 + states.Clear(); + } +} \ No newline at end of file diff --git a/Assets/03.FiniteStateMachine/RunTime/FSMController.cs.meta b/Assets/03.FiniteStateMachine/RunTime/FSMController.cs.meta new file mode 100644 index 0000000..d49012e --- /dev/null +++ b/Assets/03.FiniteStateMachine/RunTime/FSMController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0f1ae852fd60caf4da2aedfdd2b32e07 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/03.FiniteStateMachine/RunTime/FSMInitialize.cs b/Assets/03.FiniteStateMachine/RunTime/FSMInitialize.cs new file mode 100644 index 0000000..60d4635 --- /dev/null +++ b/Assets/03.FiniteStateMachine/RunTime/FSMInitialize.cs @@ -0,0 +1,46 @@ +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using UnityEngine.SceneManagement; + +public static class FSMInitialize +{ + /// + /// 状态机初始化 + /// + /// 指定场景 + /// + public static FSMManager Init(Scene targetScene) + { + GameObject targetObject = targetScene.GetRootGameObjects().FirstOrDefault(go => go.name == "FSMManger"); + FSMManager fSMManager; + + if (targetObject == null) + { + targetObject = new GameObject("FSMManger"); + SceneManager.MoveGameObjectToScene(targetObject, targetScene); + + fSMManager = new FSMManager(); + fSMManager.FSMMangerObject = targetObject; + + void OnSceneUnloaded(Scene scene) + { + // 当场景卸载时释放缓存 + if (scene.name == targetScene.name) + { + GameObject.Destroy(targetObject); + fSMManager = null; + } + } + SceneManager.sceneUnloaded += OnSceneUnloaded; + + return fSMManager; + } + else + { + Debug.LogError("场景: "+targetScene.name + "已经初始化过FSM状态机!!!"); + return null; + } + } +} diff --git a/Assets/03.FiniteStateMachine/RunTime/FSMInitialize.cs.meta b/Assets/03.FiniteStateMachine/RunTime/FSMInitialize.cs.meta new file mode 100644 index 0000000..55323a9 --- /dev/null +++ b/Assets/03.FiniteStateMachine/RunTime/FSMInitialize.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b42c8b9ea04cabf4d96cb64afb21a797 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/03.FiniteStateMachine/RunTime/FSMManager.cs b/Assets/03.FiniteStateMachine/RunTime/FSMManager.cs new file mode 100644 index 0000000..dd62904 --- /dev/null +++ b/Assets/03.FiniteStateMachine/RunTime/FSMManager.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +public class FSMManager +{ + public GameObject FSMMangerObject; + private Dictionary controllers = new Dictionary(); + private Dictionary states = new Dictionary(); + private int nextControllerId = 0; + private int nextStateId = 0; + + /// + /// 创建FSMController + /// + /// 返回创建的FSMController的识别Int值 + public int CreateFSMController() + { + if(FSMMangerObject == null) + { + Debug.LogError("FSM状态机还未初始化!!!"); + return -1; + } + else + { + int id = nextControllerId++; + GameObject newController = new GameObject("FSMController" + id); + newController.transform.SetParent(FSMMangerObject.transform); + var controller = newController.AddComponent(); + controllers[id] = controller; + return id; + } + } + + /// + /// 销毁指定FSMController + /// + /// + public void DestroyFSMController(int controllerId) + { + if (controllers.TryGetValue(controllerId, out var controller)) + { + GameObject.Destroy(controller.gameObject); + controllers.Remove(controllerId); + } + else + { + Debug.LogError("该Id的FSMController不存在或已被销毁!!!"); + } + } + + /// + /// 退出指定Controller中的所有状态 + /// + /// + public void ExitAllStateInController(int controllerId) + { + if (controllers.TryGetValue(controllerId, out var controller)) + { + controller.ExitAll(); + } + else + { + Debug.LogError("该Id的FSMController不存在或已被销毁!!!"); + } + } + + /// + /// 创建状态 + /// + /// 状态挂载的ControllerId + /// 状态行为数据 + /// + public int CreateState(int controllerId, StateDateAction stateDateAction) + { + if (controllers.TryGetValue(controllerId, out var controller)) + { + // 创建state并将其添加到指定controller生命周期中 + SingleState state = new SingleState(); + state.stateDate = stateDateAction; + controller.AddState(state); + int id = nextStateId++; + states[id] = state; + return id; + + } + else + { + Debug.LogError("该Id的FSMController不存在或已被销毁,状态初始化失败!!!"); + return -1; + } + } + + /// + /// 进入指定状态 + /// + /// + public void EnterState(int stateId) + { + if(states.TryGetValue(stateId, out var state)) + { + state.Machine.Enter(state.GetType()); + } + else + { + Debug.LogError("该Id的状态不存在!!!"); + } + } + + /// + /// 离开指定状态 + /// + /// + public void ExitState(int stateId) + { + if (states.TryGetValue(stateId, out var state)) + { + state.Machine.Exit(state.GetType()); + } + else + { + Debug.LogError("该Id的状态不存在!!!"); + } + } + + /// + /// 销毁指定状态 + /// + /// + public void DestroyState(int stateId) + { + if (states.TryGetValue(stateId, out var state)) + { + states.Remove(stateId); + } + } + + // 将状态添加到FSMController + public void AddStateToController(int controllerId, int stateId) + { + if (controllers.TryGetValue(controllerId, out var controller) && states.TryGetValue(stateId, out var state)) + { + controller.AddState(state); + } + } +} \ No newline at end of file diff --git a/Assets/03.FiniteStateMachine/RunTime/FSMManager.cs.meta b/Assets/03.FiniteStateMachine/RunTime/FSMManager.cs.meta new file mode 100644 index 0000000..939fe3f --- /dev/null +++ b/Assets/03.FiniteStateMachine/RunTime/FSMManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5ac80573cd6d59246a7fe1b954f1b57e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/03.FiniteStateMachine/RunTime/IState.cs b/Assets/03.FiniteStateMachine/RunTime/IState.cs new file mode 100644 index 0000000..72d43d7 --- /dev/null +++ b/Assets/03.FiniteStateMachine/RunTime/IState.cs @@ -0,0 +1,84 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public interface IState +{ + public FSMController Machine { get; set; } + public void OnEnter(); + public void OnExit(); + public void Update(); + public void FixedUpdate(); + public void OnInit(); + public void OnDestory(); + +} + +public abstract class AbstractState : IState +{ + public FSMController Machine { get; set; } + public abstract void OnEnter(); + public abstract void OnExit(); + public abstract void Update(); + public abstract void FixedUpdate(); + public abstract void OnInit(); + public abstract void OnDestory(); +} + +/// +/// 状态中具体行为: +/// (OnInitAction:初始化) +/// (OnEnterAction:进入) +/// (UpdateAction:循环) +/// (FixedUpdateAction:后循环) +/// (OnExitAction:离开) +/// (OnDestoryAction:销毁) +/// +public struct StateDateAction +{ + public System.Action OnEnterAction; + public System.Action OnExitAction; + public System.Action UpdateAction; + public System.Action FixedUpdateAction; + public System.Action OnInitAction; + public System.Action OnDestoryAction; +} + +/// +/// 单个状态 +/// +public class SingleState : AbstractState +{ + public StateDateAction stateDate; + public bool IsRunning; + + public override void FixedUpdate() + { + stateDate.FixedUpdateAction?.Invoke(); + } + + public override void OnDestory() + { + stateDate.OnDestoryAction?.Invoke(); + } + + public override void OnEnter() + { + stateDate.OnEnterAction?.Invoke(); + } + + public override void OnExit() + { + stateDate.OnExitAction?.Invoke(); + } + + public override void OnInit() + { + stateDate.OnInitAction?.Invoke(); + } + + public override void Update() + { + stateDate.UpdateAction?.Invoke(); + } +} diff --git a/Assets/03.FiniteStateMachine/RunTime/IState.cs.meta b/Assets/03.FiniteStateMachine/RunTime/IState.cs.meta new file mode 100644 index 0000000..07d7888 --- /dev/null +++ b/Assets/03.FiniteStateMachine/RunTime/IState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9a115cd1615ea994493a6950339d2f1e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/03.FiniteStateMachine/RunTime/PlayerFSMExample.cs b/Assets/03.FiniteStateMachine/RunTime/PlayerFSMExample.cs new file mode 100644 index 0000000..b6228ca --- /dev/null +++ b/Assets/03.FiniteStateMachine/RunTime/PlayerFSMExample.cs @@ -0,0 +1,53 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.SceneManagement; + +public class PlayerFSMExample : MonoBehaviour +{ + private int controllerId; + private int idleStateId; + private float timer = 0.0f; + private FSMManager fSMManager; + + void Start() + { + fSMManager = FSMInitialize.Init(gameObject.scene); + controllerId = fSMManager.CreateFSMController(); + StateDateAction stateDateAction = new StateDateAction() + { + OnEnterAction = () => + { + Debug.Log("进入状态"); + }, + UpdateAction = () => + { + timer += Time.deltaTime; + Debug.Log("当前时间:" + timer); + }, + OnExitAction = () => + { + Debug.Log("离开状态"); + } + }; + idleStateId = fSMManager.CreateState(controllerId, stateDateAction); + } + + void Update() + { + // 按下空格键切换到Running状态 + if (Input.GetKeyDown(KeyCode.A)) + { + fSMManager.EnterState(idleStateId); + } + if (Input.GetKeyDown(KeyCode.D)) + { + fSMManager.ExitState(idleStateId); + } + } + + void OnDestroy() + { + + } +} \ No newline at end of file diff --git a/Assets/03.FiniteStateMachine/RunTime/PlayerFSMExample.cs.meta b/Assets/03.FiniteStateMachine/RunTime/PlayerFSMExample.cs.meta new file mode 100644 index 0000000..26a4701 --- /dev/null +++ b/Assets/03.FiniteStateMachine/RunTime/PlayerFSMExample.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0deab708fd53bb4428ef48220df57be7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: