Example code (Root->Grounded):
using HSM;
using UnityEngine;
namespace Project {
public class Grounded : State {
readonly CharacterContext ctx;
public readonly Idle Idle;
public readonly Move Move;
public readonly Attacking Attacking;
public readonly Roll Roll;
public readonly Dodge Dodge;
public Grounded(StateMachine m, State parent, CharacterContext ctx) : base(m, parent) {
this.ctx = ctx;
Idle = new Idle(m, this, ctx);
Move = new Move(m, this, ctx);
Attacking = new Attacking(m, this, ctx);
Roll = new Roll(m, this, ctx);
Dodge = new Dodge(m, this, ctx);
}
protected override State GetInitialState() => Idle;
protected override State GetTransition() {
// Falling from ledge without jumping
if (ctx.isFalling && !ctx.machine.IsActive(ActionType.Fall)) {
Debug.Log($"Entering Airborne from Grounded (falling)");
return ((CharacterRoot)Parent).Airborne;
}
if (ctx.testFlags.Can(ActionType.Jump) && ctx.isJumping && !ctx.isFalling && !ctx.machine.IsActive(ActionType.Jump)) {
Debug.Log($"Entering Airborne from Grounded (jumping)");
return ((CharacterRoot)Parent).Airborne;
}
if (ctx.testFlags.Can(ActionType.Attack) && ctx.isGrounded && ctx.input.attackTriggered && !Attacking.IsActive()) {
Debug.Log($"Entering Attacking from Grounded");
ctx.input.attackTriggered = false;
return Attacking;
}
if (ctx.testFlags.Can(ActionType.Roll) && ctx.isGrounded && ctx.input.rollTriggered && !Roll.IsActive()) {
Debug.Log($"Entering Roll from Grounded");
ctx.input.rollTriggered = false;
return Roll;
}
if (ctx.testFlags.Can(ActionType.Dodge) && ctx.isGrounded && ctx.input.dodgeTriggered && !Dodge.IsActive()) {
Debug.Log($"Entering Dodge from Grounded");
ctx.input.dodgeTriggered = false;
return Dodge;
}
return null;
}
}
}
Bug: if player is in Root->Grounded->Attacking->Melee state, and SHM transitions to Root->Grounded->Roll state, OnExit() in Melee is never triggered.
FYI, State.IsActive() is a custom method I added for convenience:
public bool IsActive() {
var leaf = Machine.Root.Leaf();
for (var s = leaf; s != null; s = s.Parent) {
if (ReferenceEquals(s, this))
return true;
}
return false;
}
Example code (Root->Grounded):
Bug: if player is in
Root->Grounded->Attacking->Meleestate, and SHM transitions toRoot->Grounded->Rollstate,OnExit()inMeleeis never triggered.FYI,
State.IsActive()is a custom method I added for convenience: