Из плюсов:
- возможность создавать иерархические машины состояний
- fluent стиль использования
- можно задавать свои функции, которые будут отрабатывать при входе/выходе из состояния и во время его работы
- можно задавать условные развлетвления (пойти к состоянию А, если ... иначе к Б)
... и тд
Все лежит тут (собранная dll - нужно положить в Assets->Plugins и исходники в архиве)
Пример с лифтом, взятый из документации и обкатанный в юнити:
Синтаксис:
Используется csharp
using StateMachine;
using UnityEngine;
namespace Game.Assets.Game.Scripts.Hunter
{
public enum States
{
Healthy,
OnFloor,
Moving,
MovingUp,
MovingDown,
DoorClosed,
DoorOpen,
Error
}
public enum Events
{
ErrorOccured,
Reset,
CloseDoor,
OpenDoor,
GoUp,
GoDown,
Stop
}
public class FSMTest : MonoBehaviour
{
private PassiveStateMachine<States, Events> _elevatorFsm;
private void Start()
{
// ставим в очередь несколько событий
_elevatorFsm.Fire(Events.ErrorOccured);
_elevatorFsm.Fire(Events.Reset);
_elevatorFsm.Start();
// исполнение событий
_elevatorFsm.Fire(Events.OpenDoor);
_elevatorFsm.Fire(Events.CloseDoor);
_elevatorFsm.Fire(Events.GoUp);
_elevatorFsm.Fire(Events.Stop);
_elevatorFsm.Fire(Events.OpenDoor);
_elevatorFsm.Stop();
}
private void Awake()
{
_elevatorFsm = new PassiveStateMachine<States, Events>("Лифт");
_elevatorFsm.DefineHierarchyOn(States.Healthy)
.WithHistoryType(HistoryType.Deep)
.WithInitialSubState(States.OnFloor)
.WithSubState(States.Moving);
_elevatorFsm.DefineHierarchyOn(States.Moving)
.WithHistoryType(HistoryType.Shallow)
.WithInitialSubState(States.MovingUp)
.WithSubState(States.MovingDown);
_elevatorFsm.DefineHierarchyOn(States.OnFloor)
.WithHistoryType(HistoryType.None)
.WithInitialSubState(States.DoorClosed)
.WithSubState(States.DoorOpen);
_elevatorFsm.In(States.Healthy)
.On(Events.ErrorOccured).Goto(States.Error);
_elevatorFsm.In(States.Error)
.On(Events.Reset).Goto(States.Healthy)
.On(Events.ErrorOccured);
_elevatorFsm.In(States.OnFloor)
.ExecuteOnEntry(this.AnnounceFloor)
.ExecuteOnExit(Beep)
.ExecuteOnExit(Beep) // бип бип еще раз
.On(Events.CloseDoor).Goto(States.DoorClosed)
.On(Events.OpenDoor).Goto(States.DoorOpen)
.On(Events.GoUp)
.If(CheckOverload).Goto(States.MovingUp)
.Otherwise().Execute(this.AnnounceOverload)
.On(Events.GoDown)
.If(CheckOverload).Goto(States.MovingDown)
.Otherwise().Execute(this.AnnounceOverload);
_elevatorFsm.In(States.Moving)
.On(Events.Stop).Goto(States.OnFloor);
_elevatorFsm.Initialize(States.OnFloor);
}
private void AnnounceOverload()
{
Debug.Log("Перевес!");
}
private bool CheckOverload()
{
return false;
}
private void Beep()
{
Debug.Log("БИП БИП!");
}
private void AnnounceFloor()
{
Debug.Log("Приехали на этаж!");
}
}
}
using UnityEngine;
namespace Game.Assets.Game.Scripts.Hunter
{
public enum States
{
Healthy,
OnFloor,
Moving,
MovingUp,
MovingDown,
DoorClosed,
DoorOpen,
Error
}
public enum Events
{
ErrorOccured,
Reset,
CloseDoor,
OpenDoor,
GoUp,
GoDown,
Stop
}
public class FSMTest : MonoBehaviour
{
private PassiveStateMachine<States, Events> _elevatorFsm;
private void Start()
{
// ставим в очередь несколько событий
_elevatorFsm.Fire(Events.ErrorOccured);
_elevatorFsm.Fire(Events.Reset);
_elevatorFsm.Start();
// исполнение событий
_elevatorFsm.Fire(Events.OpenDoor);
_elevatorFsm.Fire(Events.CloseDoor);
_elevatorFsm.Fire(Events.GoUp);
_elevatorFsm.Fire(Events.Stop);
_elevatorFsm.Fire(Events.OpenDoor);
_elevatorFsm.Stop();
}
private void Awake()
{
_elevatorFsm = new PassiveStateMachine<States, Events>("Лифт");
_elevatorFsm.DefineHierarchyOn(States.Healthy)
.WithHistoryType(HistoryType.Deep)
.WithInitialSubState(States.OnFloor)
.WithSubState(States.Moving);
_elevatorFsm.DefineHierarchyOn(States.Moving)
.WithHistoryType(HistoryType.Shallow)
.WithInitialSubState(States.MovingUp)
.WithSubState(States.MovingDown);
_elevatorFsm.DefineHierarchyOn(States.OnFloor)
.WithHistoryType(HistoryType.None)
.WithInitialSubState(States.DoorClosed)
.WithSubState(States.DoorOpen);
_elevatorFsm.In(States.Healthy)
.On(Events.ErrorOccured).Goto(States.Error);
_elevatorFsm.In(States.Error)
.On(Events.Reset).Goto(States.Healthy)
.On(Events.ErrorOccured);
_elevatorFsm.In(States.OnFloor)
.ExecuteOnEntry(this.AnnounceFloor)
.ExecuteOnExit(Beep)
.ExecuteOnExit(Beep) // бип бип еще раз
.On(Events.CloseDoor).Goto(States.DoorClosed)
.On(Events.OpenDoor).Goto(States.DoorOpen)
.On(Events.GoUp)
.If(CheckOverload).Goto(States.MovingUp)
.Otherwise().Execute(this.AnnounceOverload)
.On(Events.GoDown)
.If(CheckOverload).Goto(States.MovingDown)
.Otherwise().Execute(this.AnnounceOverload);
_elevatorFsm.In(States.Moving)
.On(Events.Stop).Goto(States.OnFloor);
_elevatorFsm.Initialize(States.OnFloor);
}
private void AnnounceOverload()
{
Debug.Log("Перевес!");
}
private bool CheckOverload()
{
return false;
}
private void Beep()
{
Debug.Log("БИП БИП!");
}
private void AnnounceFloor()
{
Debug.Log("Приехали на этаж!");
}
}
}
Скорее всего должно спокойно все работать на разных платформах, но гарантии нет.
P.S. Надеюсь в правильном месте создал тему