Unity中的UI狀態機
阿新 • • 發佈:2021-01-23
using System;
using System.Collections.Generic;
using FrameWork;
using UnityEngine;
public abstract class StateSystem<T> : MonoBehaviour
{
/// <summary>
/// 狀態機
/// </summary>
protected StateMachine<T> mState;
/// <summary>
/// 狀態棧(可用於返回使用)
/// </summary>
protected Stack<T> mStateStack;
private void Awake()
{
mState = new StateMachine<T>();
mStateStack = new Stack<T>();
initialize();
initStates();
}
protected virtual void initialize()
{
}
protected virtual void initStates ()
{
}
public void OnEnable()
{
mState.OnStart();
}
public virtual void Update()
{
mState.OnUpdate();
}
public void OnDisable()
{
mState.OnStop();
}
/// <summary>
/// 切換狀態
/// </summary>
/// <param name="state">欲切換的狀態</param>
/// <param name="saveState">是否儲存上一個狀態</param>
public void ChangeState(T state, bool saveState = false)
{
try
{
if (mState.CurrentState.Equals(state))
{
return;
}
if (saveState)
{
mStateStack.Push(mState.CurrentState);
}
Debug.LogFormat("切換狀態:{0} -> {1}", mState.CurrentState, state);
mState.ChangeState(state);
}
catch (Exception e)
{
Debug.Log(e.Message);
throw;
}
}
/// <summary>
/// 當前狀態
/// </summary>
public T currentState
{
get { return mState.CurrentState; }
}
/// <summary>
/// 返回到上一個儲存的狀態
/// </summary>
/// <returns></returns>
public bool BackState()
{
if (mStateStack.Count == 0)
{
return false;
}
T lastState = mStateStack.Pop();
mStateStack.Clear();
ChangeState(lastState);
return true;
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;
namespace FrameWork
{
public class StateMachine<T>
{
private class State
{
public readonly T label;
public readonly Action onStart;
public readonly Func<T> onUpdate;
public readonly Action onStop;
public State(T label, Action onStart, Func<T> onUpdate, Action onStop)
{
this.label = label;
this.onStart = onStart;
this.onUpdate = onUpdate;
this.onStop = onStop;
}
}
/// <summary>
/// 狀態集合
/// </summary>
private readonly Dictionary<T, State> mStateDictionary;
private State mCurrentState;
/// <summary>
/// 上一個狀態
/// </summary>
private State mPreState;
/// <summary>
/// 進入的狀態名稱
/// </summary>
private T mEnterState;
/// <summary>
/// 當前狀態的label
/// </summary>
public T CurrentState
{
get { return mCurrentState.label; }
set { ChangeState(value); }
}
/// <summary>
/// 返回上一狀態label
/// </summary>
public T PreState => mPreState.label;
public bool IsRunning
{
get { return CurrentState != null; }
}
public StateMachine()
{
mStateDictionary = new Dictionary<T, State>();
}
public void OnStart()
{
if (mStateDictionary.Count == 0)
{
return;
}
mCurrentState = mStateDictionary[mEnterState];
if (mCurrentState != null && mCurrentState.onStart != null)
{
mCurrentState.onStart();
}
}
public void OnUpdate()
{
if (mCurrentState != null && mCurrentState.onUpdate != null)
{
mCurrentState.onUpdate();
}
}
public void OnStop()
{
if (mCurrentState != null && mCurrentState.onStop != null)
{
mCurrentState.onStop();
}
}
/// <summary>
/// 新增狀態
/// </summary>
/// <param name="label">狀態</param>
/// <param name="onStart">在狀態開始時呼叫</param>
/// <param name="onUpdate">在狀態期間持續呼叫</param>
/// <param name="onStop">在狀態結束時呼叫</param>
public void AddState(T label, Action onStart, Func<T> onUpdate, Action onStop)
{
State state = new State(label, onStart, onUpdate, onStop);
mStateDictionary[label] = state;
if (mCurrentState == null) //第一個新增的狀態為初始狀態
{
mCurrentState = state;
mEnterState = mCurrentState.label;
}
}
/// <summary>
/// 切換狀態
/// </summary>
/// <param name="newLabel"></param>
public void ChangeState(T newLabel)
{
if (mCurrentState != null && mCurrentState.onStop != null)
{
mCurrentState.onStop();
}
mPreState = mCurrentState;
mCurrentState = mStateDictionary[newLabel];
if (mCurrentState != null && mCurrentState.onStart != null)
{
mCurrentState.onStart();
}
}
}
}