StateExtensions Class

Summary

Various extension methods for Animancer.FSM.IState and Animancer.FSM.IOwnedState`1.
Assembly
Animancer.dll
Namespace
Animancer.FSM
Base Types
  • Object
graph BT Type-->Base0["Object"] Type["StateExtensions"] class Type type-node

Syntax

[HelpURL(APIDocumentationURL + nameof(StateExtensions))]
public static class StateExtensions

Examples

public class Character : MonoBehaviour
{
    public StateMachine<CharacterState> StateMachine { get; private set; }
}

public class CharacterState : StateBehaviour, IOwnedState<CharacterState>
{
    [SerializeField]
    private Character _Character;
    public Character Character => _Character;
    
    public StateMachine<CharacterState> OwnerStateMachine => _Character.StateMachine;
}

public class CharacterBrain : MonoBehaviour
{
    [SerializeField] private Character _Character;
    [SerializeField] private CharacterState _Jump;
    
    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            // Normally you would need to refer to both the state machine and the state:
            _Character.StateMachine.TrySetState(_Jump);
            
            // But since CharacterState implements IOwnedState you can use these extension methods:
            _Jump.TryEnterState();
        }
    }
}

Inherited Types

Unfortunately, if the field type is not the same as the T in the IOwnedState<T> implementation then attempting to use these extension methods without specifying the generic argument will give the following error:

The type 'StateType' cannot be used as type parameter 'TState' in the generic type or method 'StateExtensions.TryEnterState<TState>(TState)'. There is no implicit reference conversion from 'StateType' to 'Animancer.FSM.IOwnedState<StateType>'.

For example, you might want to access members of a derived state class like this SetTarget method:

public class AttackState : CharacterState
{
    public void SetTarget(Transform target) { }
}

public class CharacterBrain : MonoBehaviour
{
    [SerializeField] private AttackState _Attack;
    
    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            _Attack.SetTarget(...)
            // Can't do _Attack.TryEnterState();
            _Attack.TryEnterState<CharacterState>();
        }
    }
}
Unlike the _Jump example, the _Attack field is an AttackState rather than the base CharacterState so we can call _Attack.SetTarget(...) but that causes problems with these extension methods.

Calling the method without specifying its generic argument automatically uses the variable's type as the argument so both of the following calls do the same thing:

_Attack.TryEnterState();
_Attack.TryEnterState<AttackState>();
The problem is that AttackState inherits the implementation of IOwnedState from the base CharacterState class. But since that implementation is IOwnedState<CharacterState>, rather than IOwnedState<AttackState> that means TryEnterState<AttackState> does not satisfy that method's generic constraints: where TState : class, IOwnedState<TState>

That is why you simply need to specify the base class which implements IOwnedState as the generic argument to prevent it from inferring the wrong type:

_Attack.TryEnterState<CharacterState>();

Remarks

Documentation: Finite State Machines

Attributes

Type Description
HelpURLAttribute

Fields

Name Constant Value Summary
APIDocumentationURL https://kybernetik.com.au/animancer/api/Animancer.FSM/
The URL of the API documentation for the Animancer.FSM system.
static

Methods

Name Value Summary
ForceEnterState<TState>(TState) void
[Animancer Extension] Calls Animancer.FSM.IState.OnExitState on the Animancer.FSM.StateMachine`1.CurrentState then changes to the specified `state` and calls Animancer.FSM.IState.OnEnterState on it.

This method does not check Animancer.FSM.IState.CanExitState or Animancer.FSM.IState.CanEnterState. To do that, you should use TrySetState instead.
static
GetNextState<TState>(TState) TState
[Animancer Extension] Returns the Animancer.FSM.StateChange`1.NextState.
static
GetPreviousState<TState>(TState) TState
[Animancer Extension] Returns the Animancer.FSM.StateChange`1.PreviousState.
static
IsCurrentState<TState>(TState) bool
[Animancer Extension] Checks if the specified `state` is the Animancer.FSM.StateMachine`1.CurrentState in its Animancer.FSM.IOwnedState`1.OwnerStateMachine.
static
TryEnterState<TState>(TState) bool
[Animancer Extension] Attempts to enter the specified `state` and returns true if successful.

This method returns true immediately if the specified `state` is already the Animancer.FSM.StateMachine`1.CurrentState. To allow directly re-entering the same state, use Animancer.FSM.StateExtensions.TryReEnterState``1(``0) instead.
static
TryReEnterState<TState>(TState) bool
[Animancer Extension] Attempts to enter the specified `state` and returns true if successful.

This method does not check if the `state` is already the Animancer.FSM.StateMachine`1.CurrentState. To do so, use Animancer.FSM.StateExtensions.TryEnterState``1(``0) instead.
static