项目作者: hww

项目描述 :
Initial release
高级语言: C#
项目地址: git://github.com/hww/UnityTFSM.git
创建时间: 2016-01-11T09:43:16Z
项目社区:https://github.com/hww/UnityTFSM

开源协议:

下载


UnityTFSM

The demo project of the Finite State Machine used in one of my projects.

FSM Diagram

Events

Event handler - is method with data container as an argument. All message containers based on same class BaseEvent. The event handler declaration looks like:

  1. void OnStateEvent(object evt)
  2. {
  3. }

The data container can be used for reading input data and storing result of the method as well. The approach requires custom dispatching by case switch statement, but sending message to behaviour will automaticly dispach it to current state. To override the event handler for FSM behaviour, use next syntax:

  1. public override void OnStateEvent(BaseEvent evt)
  2. {
  3. switch (...)
  4. {
  5. // your event handlers for this behaviour
  6. ...
  7. default:
  8. // in other case, to deliver event to current state
  9. base.OnStateEvent(evt);
  10. break;
  11. }
  12. }

Spawning

Template - class is data container used for spawning new game objects. When new object created the object ‘s OnSpawned method will be invoked with message container (wich refers to template).

There are two methods for used by spawning system OnSpawned and OnDespawned.

  1. void OnSpawned(OnSpawnEvent evt)
  2. {
  3. // Initialize the object. Start FSM if it needs
  4. OnSpawnElevatorEvent e = evt as OnSpawnElevatorEvent;
  5. template = e.GetTemplate; // now we can access to template
  6. // Copy data from template to this instance
  7. this.foo = template.foo;
  8. this.bar = template.bar;
  9. }
  10. void OnDespawned()
  11. {
  12. // Deinitialize the object
  13. }

FSM

To implement a state machine, define new enum with required states.

  1. public enum ElevatorStates
  2. {
  3. Undefined,
  4. WaitingState,
  5. MovingState
  6. }

Then implement the behavior.

  1. public class Elevator : TFsmEntity<ElevatorStates>
  2. {
  3. }

Add methods per each available state.

  1. public class Elevator : TFsmEntity<ElevatorStates>
  2. {
  3. IEnumerator WaitingState()
  4. {
  5. }
  6. IEnumerator MovingState()
  7. {
  8. }
  9. }

Every state method’s body, starts with onEnter code block. In this block contains definition for onExit and onEvent handler.

  1. IEnumerator WaitingState()
  2. {
  3. onStateEvent = (BaseEvent evt) =>
  4. {
  5. };
  6. onStateExit = () =>
  7. {
  8. };
  9. // onEnter code block
  10. while (...)
  11. {
  12. // State arc
  13. yield
  14. }
  15. }

Other state machine methods:

Method Descrition
void StartFsm(STATES initialState, object theValue = null) Start FSM with state initialState and argument theValue
object Go(STATES nextState, object theValue = null) Start FSM with state nextState and argument theValue
object GoAndStop(STATES nextState, object theValue = null) Go to the state nextState with theValue and stop FSM
object InterruptAndGo(STATES nextState, object theValue = null) Same as GO but print the text info about transition to log file
object GoBack() Return to previous state

Example starting new FSM and switching a state:

  1. public override void OnSpawned(object evt)
  2. {
  3. base.OnSpawned(evt); // initialize parent class
  4. StopAllCoroutines();
  5. OnSpawnElevatorEvent e = evt as OnSpawnElevatorEvent;
  6. template = e.GetTemplate; // now we can access to template
  7. // initialize this object here
  8. this.foo = template.foo;
  9. this.bar = template.bar;
  10. ...
  11. StartFsm(ElevatorStates.WaitingState); // start FSM here
  12. }
  13. IEnumerator MovingState()
  14. {
  15. onStateEvent = (BaseEvent evt) =>
  16. {
  17. Debug.LogFormat("MovingState.onStateEvent({0})",evt);
  18. };
  19. onStateExit = () =>
  20. {
  21. Debug.LogFormat("MovingState.onStateExit()");
  22. };
  23. while (stateTime < 1f)
  24. yield return null;
  25. Go(ElevatorStates.WaitingState); // switch FSM state
  26. }

Additionally the FSM has next fields:

Type Field Description
STATE state Current state
STATE previousState Previous state
object stateValue State’s value
float stateStartAt State starts at
float stateTime Time since state stars

Conclusion

In general the approach works well with simple projects. :)