summaryrefslogtreecommitdiff
path: root/WorldlineKeepers/Assets/Scripts/Tools/Statemachine
diff options
context:
space:
mode:
Diffstat (limited to 'WorldlineKeepers/Assets/Scripts/Tools/Statemachine')
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/Statemachine/AsyncStatemachine.cs254
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/Statemachine/AsyncStatemachine.cs.meta11
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/Statemachine/Statemachine.cs249
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/Statemachine/Statemachine.cs.meta11
4 files changed, 525 insertions, 0 deletions
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/Statemachine/AsyncStatemachine.cs b/WorldlineKeepers/Assets/Scripts/Tools/Statemachine/AsyncStatemachine.cs
new file mode 100644
index 0000000..605f737
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/Statemachine/AsyncStatemachine.cs
@@ -0,0 +1,254 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using MEC;
+
+namespace WK
+{
+
+ /// <summary>
+ /// 公共状态机
+ /// </summary>
+ public class AsyncStatemachine
+ {
+
+ public delegate void LoadStateComplete();
+
+ public abstract class State
+ {
+ public AsyncStatemachine owner;
+ public int stateID; // stateID可以是string.GetHashCode() 以提供扩展性
+ public abstract IEnumerator<float> OnStart();
+ public abstract IEnumerator<float> OnEnd();
+ public abstract void OnUpdate(float deltaTime);
+ }
+
+ public const int NULL_STATE_ID = -1;
+ public const float COROUINT_DELTIME = 0.01f;
+
+ private Dictionary<int/*stateID*/, State> allState = new Dictionary<int, State>();
+ private int curStateID = NULL_STATE_ID;
+ private int stateIDDistributor = 0;
+ // 在状态切换完成前为false,不能进行update
+ private bool isUpdateActive = false;
+
+ /// <summary>
+ /// 添加状态,并返回在状态机中的ID
+ /// </summary>
+ /// <param name="newState"></param>
+ /// <returns></returns>
+ public int RegisterState(State newState)
+ {
+ if (newState == null)
+ return NULL_STATE_ID;
+ if (stateIDDistributor + 1 >= int.MaxValue)
+ {
+ Debug.LogError("状态机添加状态失败,此状态机中添加的状态过多");
+ return NULL_STATE_ID;
+ }
+ ++stateIDDistributor;
+ if (!allState.ContainsKey(stateIDDistributor))
+ {
+ newState.owner = this;
+ newState.stateID = stateIDDistributor;
+ allState.Add(stateIDDistributor, newState);
+ return stateIDDistributor;
+ }
+ Debug.LogError("状态机添加状态失败,状态已经存在");
+ return NULL_STATE_ID;
+ }
+
+ public bool RemoveState(State state)
+ {
+ if (state != null)
+ {
+ return RemoveState(state.stateID);
+ }
+ Debug.LogError("状态机删除状态失败,状态为空");
+ return false;
+ }
+
+ public bool RemoveState(int stateID)
+ {
+ if (allState.ContainsKey(stateID))
+ {
+ allState.Remove(stateID);
+ return true;
+ }
+ Debug.LogError("状态机删除状态失败,该状态不存在,stateID = " + stateID);
+ return false;
+ }
+
+ /// <summary>
+ /// 开始运行状态机
+ /// </summary>
+ /// <param name="stateID"></param>
+ /// <returns></returns>
+ public bool Start(int stateID)
+ {
+ if (!HasBegin())
+ {
+ ForceGotoState(stateID);
+ return true;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// 结束状态机
+ /// </summary>
+ /// <returns></returns>
+ public bool Stop()
+ {
+ if (HasBegin())
+ {
+ ForceGotoState(NULL_STATE_ID);
+ return true;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// 更新状态机
+ /// </summary>
+ /// <param name="deltaTime"></param>
+ public void Update(float deltaTime)
+ {
+ if (HasBegin())
+ {
+ UpdateState(curStateID, deltaTime);
+ }
+ }
+
+ public bool GotoState(int stateID, bool skipStartFunc = false, bool bForce = false, LoadStateComplete callback = null)
+ {
+ if (HasBegin())
+ return ForceGotoState(stateID, skipStartFunc, bForce, callback);
+ return false;
+ }
+
+ public bool ForceGotoState(int nextStateID, bool skipStartFunc = false, bool bForce = false, LoadStateComplete callback = null)
+ {
+ if (curStateID != nextStateID || bForce)
+ {
+ Timing.Instance.RunCoroutineOnInstance(AyncForceGotoState(nextStateID, skipStartFunc, callback));
+ return true;
+ }
+ if (callback != null)
+ callback();
+ return false;
+ }
+
+ /// <summary>
+ /// 异步的切换到某个状态
+ /// </summary>
+ /// <returns></returns>
+ private IEnumerator<float> AyncForceGotoState(int nextStateID, bool skipStartFunc = false, LoadStateComplete callback = null)
+ {
+ isUpdateActive = false;
+ CoroutineHandle handle = Timing.RunCoroutine(EndState(curStateID));
+ while (handle.IsValid)
+ {
+ yield return Timing.WaitForSeconds(COROUINT_DELTIME);
+ }
+ curStateID = nextStateID;
+ if (!skipStartFunc)
+ {
+ CoroutineHandle handle2 = Timing.RunCoroutine(StartState(curStateID));
+ while (handle2.IsValid)
+ {
+ yield return Timing.WaitForSeconds(COROUINT_DELTIME);
+ }
+ }
+ if (callback != null)
+ callback();
+ isUpdateActive = true;
+ }
+
+ public int GetCurStateID()
+ {
+ return curStateID;
+ }
+
+ public bool HasBegin()
+ {
+ if (curStateID != NULL_STATE_ID && allState.ContainsKey(curStateID))
+ return true;
+ return false;
+ }
+
+ public bool IsInState(int stateID)
+ {
+ if (HasBegin())
+ {
+ return curStateID == stateID;
+ }
+ return false;
+ }
+
+ public State GetState(int stateID)
+ {
+ if (allState.ContainsKey(stateID))
+ {
+ return allState[stateID];
+ }
+ return null;
+ }
+
+ public void Clean()
+ {
+ allState.Clear();
+ curStateID = NULL_STATE_ID;
+ stateIDDistributor = 0;
+ }
+
+ public void ResetCurState()
+ {
+ curStateID = NULL_STATE_ID;
+ }
+
+ private IEnumerator<float> StartState(int stateID)
+ {
+ if (HasBegin())
+ {
+ State state = GetState(stateID);
+ if (state != null)
+ {
+ CoroutineHandle handle = Timing.RunCoroutine(state.OnStart());
+ while (handle.IsValid)
+ {
+ yield return Timing.WaitForSeconds(COROUINT_DELTIME);
+ }
+ }
+ }
+ }
+
+ private IEnumerator<float> EndState(int stateID)
+ {
+ if (HasBegin())
+ {
+ State state = GetState(stateID);
+ if (state != null)
+ {
+ CoroutineHandle handle = Timing.RunCoroutine(state.OnEnd());
+ while (handle.IsValid)
+ {
+ yield return Timing.WaitForSeconds(COROUINT_DELTIME);
+ }
+ }
+ }
+ }
+
+ private void UpdateState(int stateID, float deltaTime)
+ {
+ if (HasBegin())
+ {
+ State state = GetState(stateID);
+ if (state != null)
+ state.OnUpdate(deltaTime);
+ }
+ }
+
+ }
+
+}
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/Statemachine/AsyncStatemachine.cs.meta b/WorldlineKeepers/Assets/Scripts/Tools/Statemachine/AsyncStatemachine.cs.meta
new file mode 100644
index 0000000..e2b8d49
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/Statemachine/AsyncStatemachine.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c43b283f086a24140b0e6e6e0e9efbef
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/Statemachine/Statemachine.cs b/WorldlineKeepers/Assets/Scripts/Tools/Statemachine/Statemachine.cs
new file mode 100644
index 0000000..56dd28b
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/Statemachine/Statemachine.cs
@@ -0,0 +1,249 @@
+using UnityEngine;
+using System.Collections;
+using System.Collections.Generic;
+using Newtonsoft.Json.Utilities;
+
+namespace WK
+{
+
+ public class BaseStateMachine
+ {
+ public delegate void StateEvent();
+ public delegate bool StateFinishChecker();
+ public class State
+ {
+ public BaseStateMachine owner;
+ public int stateId;
+
+ public virtual void BeginState()
+ {
+ //reserve function
+ }
+ public virtual void EndState()
+ {
+ //reserve function
+ }
+ //时间单位是毫秒
+ public virtual bool UpdateState(int deltaTimeMS)
+ {
+ return true;
+ }
+ }
+
+ private Dictionary<int/*state id*/, State> stateDic = new Dictionary<int/*state id*/, State>();
+ private int currentStateId = -1;
+ private int stateIdDistributor = 0;
+
+ private int recordLastStateId = -1;
+
+ public int RegisterState(State newState)
+ {
+ if (newState != null)
+ {
+ if (stateIdDistributor + 1 > int.MaxValue)
+ {
+ Debug.LogError("状态机添加状态失败:一个状态机中添加了过多的状态!");
+ return -1;
+ }
+
+ stateIdDistributor++;
+ if (!stateDic.ContainsKey(stateIdDistributor))
+ {
+ stateDic.Add(stateIdDistributor, newState);
+ newState.owner = this;
+ newState.stateId = stateIdDistributor;
+ return stateIdDistributor;
+ }
+ }
+ Debug.LogError("状态机添加状态失败:无效的新状态或新状态已存在!");
+ return -1;
+ }
+
+ public bool RemoveState(State toBeRemoveState)
+ {
+ if (toBeRemoveState != null)
+ return RemoveState(toBeRemoveState.stateId);
+ Debug.LogError("状态机删除状态失败:无效的状态!");
+ return false;
+ }
+
+ public bool RemoveState(int stateId)
+ {
+ if (stateDic.ContainsKey(stateId))
+ {
+ stateDic.Remove(stateId);
+ return true;
+ }
+ Debug.LogError("状态机删除状态失败:该状态不存在!");
+ return false;
+ }
+
+ public bool Begin(int beginStateId)
+ {
+ if (!HasBegin())
+ {
+ ForceGoToState(beginStateId, false);
+ return true;
+ }
+
+ return false;
+ }
+
+ public bool Stop()
+ {
+ if (HasBegin())
+ {
+ ForceGoToState(-1);
+ return true;
+ }
+
+ return false;
+ }
+
+ public bool GoToState(int newStateId, bool skipBeginFunc = false, bool forceLoad = false)
+ {
+ if (HasBegin())
+ {
+ return ForceGoToState(newStateId, skipBeginFunc, forceLoad);
+ }
+ return false;
+ }
+
+ private bool ForceGoToState(int newStateId)
+ {
+ return ForceGoToState(newStateId, false);
+ }
+ private bool ForceGoToState(int newStateId, bool skipBeginFunc, bool bForce = false)
+ {
+ if (currentStateId != newStateId || bForce)
+ {
+ OnStateEnd(currentStateId);
+ currentStateId = newStateId;
+ if (!skipBeginFunc) OnStateBegin(currentStateId);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="filterState">剔除的state</param>
+ public void RecordCurrentState(int filterState)
+ {
+ if (currentStateId != filterState)
+ {
+ recordLastStateId = currentStateId;
+ }
+ }
+
+ public void ClearRecordState()
+ {
+ recordLastStateId = -1;
+ }
+
+ public void RevertToRecordState(int fallbackState, bool skipBeginFunc, bool bForce = false)
+ {
+ if (recordLastStateId >= 0 && stateDic.ContainsKey(recordLastStateId))
+ {
+ GoToState(recordLastStateId, skipBeginFunc, bForce);
+ }
+ else if (fallbackState >= 0 && stateDic.ContainsKey(fallbackState))
+ {
+ GoToState(fallbackState, skipBeginFunc, bForce);
+ }
+ }
+
+
+ //时间单位是毫秒
+ public void OnUpdate(int mSecDeltaTime)
+ {
+ if (HasBegin())
+ {
+ UpdateState(currentStateId, mSecDeltaTime);
+ }
+ }
+
+ public bool HasBegin()
+ {
+ if (currentStateId != -1 && stateDic.ContainsKey(currentStateId))
+ return true;
+ else
+ return false;
+ }
+
+ public bool IsInState(int stateId)
+ {
+ if (HasBegin())
+ {
+ return currentStateId == stateId;
+ }
+ return false;
+ }
+
+
+ public int GetCurrentStateId()
+ {
+ return currentStateId;
+ }
+
+ public State GetState(int stateId)
+ {
+ if (stateDic.ContainsKey(stateId))
+ {
+ return stateDic[stateId];
+ }
+ return null;
+ }
+
+ public void Clean()
+ {
+ stateDic.Clear();
+ currentStateId = -1;
+ stateIdDistributor = 0;
+ recordLastStateId = -1;
+ }
+
+ /// <summary>
+ /// 重置当前状态(置为-1)
+ /// </summary>
+ public void ResetCurrentState()
+ {
+ currentStateId = -1;
+ }
+
+ private void OnStateBegin(int stateId)
+ {
+ if (HasBegin())
+ {
+ State state = GetState(stateId);
+ if (state != null)
+ state.BeginState();
+ }
+ }
+
+ private void OnStateEnd(int stateId)
+ {
+ if (HasBegin())
+ {
+ State state = GetState(stateId);
+ if (state != null)
+ state.EndState();
+ }
+ }
+ //时间单位是毫秒
+ private void UpdateState(int stateId, int mSecDeltaTime)
+ {
+ if (HasBegin())
+ {
+ State state = GetState(stateId);
+ if (state != null)
+ state.UpdateState(mSecDeltaTime);
+ }
+ }
+ }
+
+} \ No newline at end of file
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/Statemachine/Statemachine.cs.meta b/WorldlineKeepers/Assets/Scripts/Tools/Statemachine/Statemachine.cs.meta
new file mode 100644
index 0000000..1f9dc33
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/Statemachine/Statemachine.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 740b9ccdbc7196546acfadecbcbd71f0
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: