Skip to content

Bug: OnExit() not triggering on specific transitions #1

Description

@MJRamon

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;
        }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions