第一篇寫好了接口,這篇來寫具體實作。
首先是State類,他要實作IState接口:
public class JyState : IState
{
public string Name { get { return _name; } }
public string Tag
{
get { return _tag; }
set { _tag = value; }
}
public float Timer { get { return _timer; } }
public IStateMachine Parent { get { return _parent; } }
public List<ITransition> Transitions { get { return _transitions; } }
public JyState(string name)
{
_name = name;
_transitions = new List<ITransition>();
}
/// <summary>
/// 添加狀态轉換
/// </summary>
/// <param name="transition"></param>
public void AddTransition(ITransition transition)
{
if(!_transitions.Contains(transition))
_transitions.Add(transition);
else
{
// log warining : 該轉換已經存在
}
}
/// <summary>
/// 進入本狀态
/// </summary>
/// <param name="prev"></param>
public virtual void OnEnter(IState prev)
{
_timer = 0;
_index = 0;
_isWork = true;
}
/// <summary>
/// 離開本狀态
/// </summary>
/// <param name="next"></param>
public virtual void OnExit(IState next)
{
_timer = 0;
_index = 0;
_isWork = false;
}
/// <summary>
/// 每幀執行
/// </summary>
/// <param name="deltaTime"></param>
public virtual void OnUpdate(float deltaTime)
{
if (!_isWork) return;
_timer += deltaTime;
if (_transitions.Count < 1) return;
// 如果檢測能夠轉換,則進入轉換函數中
if (_workingTransition != null && _workingTransition.OnCheck())
{
// 如果轉換完成
if (_workingTransition.OnCompleteCallBack())
{
DoTransition(_workingTransition);
}
return;
}
_index += 1;
if (_index >= _transitions.Count) _index = 0;
_workingTransition = _transitions[_index];
}
/// <summary>
/// 設定本狀态的父狀态機
/// </summary>
/// <param name="stateMachine"></param>
public void SetStateMachine(IStateMachine stateMachine)
{
_parent = stateMachine;
}
protected string _tag;
protected string _name;
protected float _timer;
protected bool _isWork;
protected int _index;
protected IStateMachine _parent;
protected List<ITransition> _transitions;
protected ITransition _workingTransition;
/// <summary>
/// 執行轉換
/// </summary>
/// <param name="transition"></param>
protected virtual void DoTransition(ITransition transition)
{
Parent.CurState.OnExit(transition.ToState);
Parent.SetCurState(transition.ToState);
Parent.CurState.OnEnter(transition.FromState);
}
}
狀态機StateMachine實作IStateMachine接口:
public class JyStateMachine : JyState, IStateMachine
{
public IState CurState { get { return _curState; } }
public IState DefaultState { get { return _defaultState; } }
public Dictionary<string, IState> States { get { return _states; } }
public JyStateMachine(string name, IState defaultState) : base(name)
{
_states = new Dictionary<string, IState>();
AddState(defaultState);
_defaultState = defaultState;
_curState = defaultState;
_curState.OnEnter(null);
}
/// <summary>
/// 添加狀态
/// </summary>
/// <param name="state"></param>
public void AddState(IState state)
{
if(!_states.ContainsKey(state.Name))
{
_states.Add(state.Name, state);
state.SetStateMachine(this);
}
else
{
// log warining: 已有該 state 狀态
}
}
/// <summary>
/// 獲得狀态
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IState GetStateWithName(string name)
{
return _states != null ? _states[name] : null;
}
/// <summary>
/// 獲得狀态
/// </summary>
/// <param name="tag"></param>
/// <returns></returns>
public IState GetStateWithTag(string tag)
{
foreach(var state in _states.Values)
{
if (state.Tag == tag)
return state;
}
return null;
}
/// <summary>
/// 移除狀态
/// </summary>
/// <param name="state"></param>
public void RemoveState(IState state)
{
if (_states.ContainsKey(state.Name)) _states.Remove(state.Name);
if (_defaultState == _curState && _curState == state)
{
_curState = _states.Count > 0 ? _states[_states.Keys.ToArray()[0]] : null;
_defaultState = _curState;
}
else if(_defaultState != _curState && _defaultState == state)
{
_defaultState = _curState;
}
else if(_curState != _defaultState && _curState == state)
{
_curState = _states.Count > 0 ? _states[_states.Keys.ToArray()[0]] : null;
}
}
/// <summary>
/// 設定目前狀态
/// </summary>
/// <param name="state"></param>
public void SetCurState(IState state)
{
if(state == null)
{
// log warining : 傳入的 state 為空!
return;
}
_curState = state;
}
public override void OnEnter(IState prev)
{
base.OnEnter(prev);
_curState.OnEnter(prev);
}
public override void OnExit(IState next)
{
base.OnExit(next);
_curState.OnExit(next);
}
public override void OnUpdate(float deltaTime)
{
base.OnUpdate(deltaTime);
_curState.OnUpdate(deltaTime);
}
private IState _curState;
private IState _defaultState;
private Dictionary<string, IState> _states;
}
狀态轉換 StateTransition 實作 IStateTransition接口:
public class JyTransition : ITransition
{
public JyTransition(string name, IState from, IState to)
{
_to = to;
_from = from;
_name = name;
}
public string Name { get { return _name; } }
public IState ToState { get { return _to; } }
public IState FromState { get { return _from; } }
/// <summary>
/// 檢測能否轉換
/// </summary>
/// <returns></returns>
public virtual bool OnCheck()
{
return true;
}
/// <summary>
/// 檢測轉換函數是否執行完畢
/// </summary>
/// <returns></returns>
public virtual bool OnCompleteCallBack()
{
return true;
}
protected IState _from;
protected IState _to;
protected string _name;
}
三個關鍵類實作完成後,最後該講如何使用,這裡我們用遊戲角色的 移動、跳躍、攻擊、待機 這四個狀态來做例子講解。
講解放在第三篇。