State-Machine FSM

You can download the FSM from GitHub below:

github-mark@1200x630

Using the FSM

To illustrate the use of the FSM. I will develop a simple FSM for a turret.
We have four states, Wait, Aim, Shoot, Die.

Wait is our initial state.

  • Wait can lead to Aim and Die.
  • Aim can lead to Wait, Shoot and Die
  • Shoot can lead to Aim and Die
  • Die can lead to Wait

 

public class Turret : StateMachine 
{
	public Transform player = null;
	private float aimDistance = 10f;
	private float shootDistance = 5f;
	void Awake()
	{
		InitializeStateMachine<State> (State.Wait, true);
		AddTransitionsToState (State.Wait, new System.Enum[]{ State.Aim ,State.Die });
		AddTransitionsToState (State.Aim, new System.Enum[]{ State.Wait ,State.Shoot, State.Die });
		AddTransitionsToState (State.Shoot, new System.Enum[]{ State.Aim ,State.Die });
		AddTransitionsToState (State.Die, new System.Enum[]{ State.Wait });
		//this.player = GameObject.Find ("Player").transform;
	}
	private void EnterWait(Enum previous)
	{
		// init some stuff
		// Enable renderer
	}
	private void UpdateWait()
	{
		if(Vector3.Distance (this.player.position, this.transform.position) < this.aimDistance)
	 	{
			ChangeCurrentState(State.Aim);
		}
	}

	private void UpdateAim()
	{
		SetRotation ();
		if(Vector3.Distance (this.player.position, this.transform.position) < this.shootDistance)
		{
			ChangeCurrentState(State.Shoot);
		}
	}
	private float shootTimer = 1f;
	private float timer = 0f;
	private void UpdateShoot()
	{
		SetRotation ();
		if (this.timer > this.shootTimer) {
			Shoot ();
			this.timer = 0f;
		}
		this.timer += Time.deltaTime;
		if(Vector3.Distance (this.player.position, this.transform.position) > this.shootDistance)
		{
			ChangeCurrentState(State.Aim);
		}
	}
	private void EnterDie(Enum previous)
	{
		// Disable renderer

	}
	private void SetRotation()
	{
		Quaternion targetRotation = Quaternion.LookRotation (this.player.position - this.transform.position);
		this.transform.rotation = Quaternion.Lerp (this.transform.rotation, targetRotation, Time.deltaTime);
	}
	private void Shoot(){ Debug.Log(" Pow "); }
	enum State{ Wait, Aim, Shoot, Die }
}

Awake sets all needed state and legal transition. It also sets the initial state.
Each state checks for distance to change the current state. Each state, can add extra action like rotation or shooting.
The bonus lies in the clarity of each state method. No need for long if statements.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s