using System;
using System.Reflection;
using UnityEngine;
public class StateMachine<TStates> where TStates : Enum
{
private TStates initialState;
private TStates currentState;
private MonoBehaviour component;
public StateMachine(MonoBehaviour component)
{
this.component = component;
}
public StateMachine(MonoBehaviour component, TStates initialState)
{
this.component = component;
this.initialState = initialState;
SetState(this.initialState);
}
public void SetState(TStates newState)
{
Type componentType = component.GetType();
if (currentState != null)
{
if (currentState.Equals(newState))
return;
componentType.GetMethod("On" + currentState + "Exit", BindingFlags.NonPublic | BindingFlags.Instance)?.Invoke(component, null);
}
else
initialState = newState;
currentState = newState;
componentType.GetMethod("On" + currentState + "Enter", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(component, null);
}
public void Update()
{
Type componentType = component.GetType();
if (currentState != null)
componentType.GetMethod("On" + currentState + "Update", BindingFlags.NonPublic | BindingFlags.Instance)?.Invoke(component, null);
}
public void Reset()
{
if (initialState != null)
SetState(initialState);
}
}
我有一个有限状态机,我试着自己做,它工作得很好。然而,人们告诉我,这不是打字安全。
他们告诉我使用switch语句,但我不知道如何实现它们。
有什么办法可以让它打字安全吗?
public interface IStateHandle<TStates> where TStates : Enum
{
void OnEnter(TStates state);
void OnUpdate(TStates state);
void OnExit(TStates state);
}
public class StateMachine<TStates> where TStates : Enum
{
IStateHandle<TStates> _handle;
TStates _currentState;
public StateMachine(IStateHandle<TStates> handle)
{
_handle = handle;
}
public void Update()
{
_handle.OnUpdate(_currentState);
}
}
例如,您可以将您的状态替换为只使用方法的状态类型,例如:
public interface IState{
void Exit();
void Enter();
void Update();
}
并为您想要的每个状态提供一个实现。您还可以有一个实现,将每个方法的实现委托给一个委托。
通过引入公共基类或接口,您可以轻松地使状态机类型安全,您的状态应该从中继承。鉴于此,实现状态机设计模式非常简单:
public interface IState
{
void Handle(Context context);
}
public class Walk : IState
{
public void Handle(Context context)
{
context.State = new Shoot();
}
}
public class Shoot : IState
{
public void Handle(Context context)
{
context.State = new Walk();
}
}
public class Context
{
public Context(IState state)
{
this.State = state;
}
public IState State { get; set; }
public void Request()
{
this.State.Handle(this);
}
}