State Pattern Using Unity
Learn all about the Finite State Machine design pattern in Unity. Then implement it to control the movement of your own character! By Najmm Shora.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
State Pattern Using Unity
20 mins
Sneaking Under the Table
Open Ducking.cs. Notice Ducking
also inherits from the Grounded
class for the same reasons Standing
does. Add the following override
methods and save the script:
public override void Enter()
{
base.Enter();
character.SetAnimationBool(character.crouchParam, true);
speed = character.CrouchSpeed;
rotationSpeed = character.CrouchRotationSpeed;
character.ColliderSize = character.CrouchColliderHeight;
belowCeiling = false;
}
public override void Exit()
{
base.Exit();
character.SetAnimationBool(character.crouchParam, false);
character.ColliderSize = character.NormalColliderHeight;
}
public override void HandleInput()
{
base.HandleInput();
crouchHeld = Input.GetButton("Fire3");
}
public override void LogicUpdate()
{
base.LogicUpdate();
if (!(crouchHeld || belowCeiling))
{
stateMachine.ChangeState(character.standing);
}
}
public override void PhysicsUpdate()
{
base.PhysicsUpdate();
belowCeiling = character.CheckCollisionOverlap(character.transform.position +
Vector3.up * character.NormalColliderHeight);
}
- Inside
Enter
, the parameter to trigger the crouch animation is set to true which enables the crouch animation. Thecharacter.CrouchSpeed
andcharacter.CrouchRotationSpeed
properties set thespeed
androtation
which return the intended translation and angular speed of the character while crouching.
Next,character.CrouchColliderHeight
sets the collider size of the character, which returns the intended collider height while crouching. Finally,belowCeiling
is reset to false. - Inside
Exit
, the parameter for crouch animation is set to false. This would disable the crouch animation. Afterwards the collider height is set to normal intended height returned bycharacter.NormalColliderHeight
. - Inside
HandleInput
,crouchHeld
is set to accept the user input. In the Main scene, holding down Shift will setcrouchHeld
to true. - Inside
PhysicsUpdate
, thebelowCeiling
variable is set by passing in theVector3
point near the Character GameObject’s head toCheckCollisionOverlap
by. If there is a collision around that point, it means the Character is below a ceiling of some sort. - Inside
LogicUpdate
, you check to see if eithercrouchHeld
orbelowCeiling
is true. If neither of them is true,movementSM.CurrentState
changes tocharacter.standing
.
Build and click Play. Now you should be able to move around. If you press Shift, the Character will crouch and you can move around while crouching.
You should also be able to go under the platforms. If you release Shift while underneath the platforms, the Character will continue crouching until you leave its cover.
Up, Up and Away!
Open Jumping.cs. You’ll see a method named Jump
. Don’t worry about its specifics but understand it’s used to make the Character jump with physics, animation and magic! :]
Now add the usual override
methods and save the script
public override void Enter()
{
base.Enter();
SoundManager.Instance.PlaySound(SoundManager.Instance.jumpSounds);
grounded = false;
Jump();
}
public override void LogicUpdate()
{
base.LogicUpdate();
if (grounded)
{
character.TriggerAnimation(landParam);
SoundManager.Instance.PlaySound(SoundManager.Instance.landing);
stateMachine.ChangeState(character.standing);
}
}
public override void PhysicsUpdate()
{
base.PhysicsUpdate();
grounded = character.CheckCollisionOverlap(character.transform.position);
}
- Inside
Enter
, theSoundManager
singleton plays the jump sound. Afterwards,grounded
is reset to its default value. FinallyJump
gets called. - Inside
PhysicsUpdate
, theVector3
point near the Character’s feet is sent toCheckCollisionOverlap
, which meansgrounded
will be set to true if the Character is on ground. - In
LogicUpdate
whengrounded
is true, you callTriggerAnimation
for the landing animation, a landing audio plays andmovementSM.CurrentState
changes tocharacter.standing
.
Finally, with this, you’ve fully implemented the movement FSM using the State Pattern. Build and play. Use Space to make the character jump.
Now you can say, “my code is in a state!” with a smile on your face! :]
Where to Go From Here?
You can use the Download Materials button at the top and bottom of this tutorial to download both the starter and final projects.
While state machines are useful they come with their own limitations. Concurrent State Machines and Pushdown Automata tackle some of those limitations. You can read more about them in the book Game Programming Patterns by R.Nystrom.
You can also delve deeper by exploring behavioral trees for making advanced in-game entities.
I hope you found this tutorial useful and enjoyed learning the topic. Please feel free to join the forum below for any questions or comments.