Я реализовал простой конечный автомат в Unity, который использовал в нескольких проектах, но постоянно сталкиваюсь с одной и той же проблемой: как мне общаться с состоянием объекта из внешнего скрипта?
Скажем, у меня есть класс Player с состояниями Idle и PoweredUp. Я хочу отправить событие из другого класса, которое имеет разные результаты в зависимости от того, в каком состоянии находится класс игрока (например, диспетчер повреждений отправляет событие ApplyDamage, которое убивает игрока, если он находится в состоянии Idle). и переводит их в состояние Idle, если они находятся в состоянии PoweredUp).
В компании, в которой я работал, был язык сценариев, который делал это через события, где вы могли транслировать события в сценарий состояния с любым количеством параметров, и они вели бы себя по-разному в зависимости от того, в каком состоянии находится сценарий. Возможно ли это в C#? ? Есть ли лучший подход? Что было бы лучшим способом спроектировать это?
Сценарий конечного автомата:
public class StateMachine {
private State previousState;
private State currentState;
public State CurrentState { get { return currentState; } set { currentState = value; } }
public void ChangeState(State newState)
{
if (currentState != null)
{
currentState.Exit();
}
previousState = currentState;
currentState = newState;
currentState.Enter();
}
public void ExecuteStateUpdate()
{
if (currentState != null)
{
currentState.Execute();
}
}
public void ReturnToPreviousState()
{
currentState.Exit();
currentState = previousState;
currentState.Enter();
}
}
Сценарий состояния:
[System.Serializable]
public abstract class State {
public virtual void Enter() { }
public virtual void Execute() { }
public virtual void Exit() { }
}
Пример скрипта:
public class Player : MonoBehaviour
{
StateMachine stateMachine = new StateMachine();
Idle idleState => new Idle(this);
PoweredUp poweredUpState => new PoweredUp(this);
private void Start()
{
stateMachine.ChangeState(idleState);
}
private void Update()
{
stateMachine.ExecuteStateUpdate();
}
// -----------------------------------------------------
public abstract class Base : State
{
protected Player owner;
public Base(Player owner) { this.owner = owner; }
}
// -----------------------------------------------------
public class Idle : Base
{
public Idle(Player owner) : base(owner) { }
public override void Execute ()
{
// do update stuff
}
}
// -----------------------------------------------------
public class PoweredUp : Base
{
public PoweredUp(Player owner) : base(owner) { }
public override void Enter()
{
// play power up animation
// play power up sound
}
}
}
До сих пор я пытался добавить Event(string eventName)
в класс State, а затем запустить функцию переключения для eventName в моих состояниях, но это не позволяет мне передавать параметры с событием и опирается на строки, которые быстро становятся беспорядочными.
Я также только что добавил функции вне состояний, которые проверяют, какое значение установлено для currentState, а затем ведут себя соответствующим образом, но это полностью сводит на нет весь смысл сценария состояния.
Любая помощь высоко ценится!
Action
и передать обратный вызов с любым количеством параметров.. или, если он должен вернуть определенное значение, используйтеFunc
.. мне немного неясно, что именно вы хотите передать и выполнить.. может Вы добавляете несколько примеров для этого? - person derHugo   schedule 11.08.2020