Find all Animator transitions

I’m creating a 2d game and the animation transitions 's exit time and transition durations are set to numbers which I don’t want i.e not 1 for exit time and 0 for transition duration.

How to find and set all the transitions’ settings (animation duration/ exit time) of a given animator programmatically?

Ok I found a decent way

var stateMachine = _animatorController.layers[0].stateMachine;
            var states = stateMachine.states;

            List<AnimatorStateTransition> allTransitions = new List<AnimatorStateTransition>();
            foreach (var state in states)
            {
                allTransitions.AddRange(state.state.transitions);
            }

            foreach (var transition in allTransitions)
            {
                transition.duration = 0;
                transition.exitTime = 1;
            }

The _animatorController is something I feed to my Editor Window with:
_animatorController = (AnimatorController)EditorGUILayout.ObjectField(_animatorController,
typeof(AnimatorController), true);

I don’t know how to do this automatically every time a new transition is created, probably through events but I’m not familiar with that kind of stuff, so right now what I do is simply clean the specific Animator Controller.
You could also get every Animation Controller in the project to do on every Animation Controller.

thanks. what class are these “var’s”?
a bit unreadable
_animatorController is it a “RuntimeAnimatorController”?
or an “Animator”?
Or something entirely else?

Animator and RuntimeAnimatorController dont have a “layers” array.

_animatorController is AnimatorController (class).

I know this is an old thread, but it was one of the first Google hits that I got. So, for anyone like @OC_Raiz that’s interested, this is my code. Hope it helps.

var controller = animator.runtimeAnimatorController;
            var stateMachine = ((AnimatorController)controller).layers[layerIndex].stateMachine;
            var states = stateMachine.states;

            List<AnimatorStateTransition> allTransitions = new List<AnimatorStateTransition>();
            foreach (var state in states)
            {
                allTransitions.AddRange(state.state.transitions);
            }

            foreach (var transition in allTransitions)
            {
                transition.duration = 0;
                transition.exitTime = 1;
           }
3 Likes

I have build this utility MonoBehaviour that automatically modifies all transitions in OnValidate

[RequireComponent(typeof(Animator))]
public class StateAnimator : MonoBehaviour
{
    private Animator _animator;

#if UNITY_EDITOR // put using UnityEditor statement in precompiler flags as well
    private void OnValidate()
    {
        _animator = GetComponent<Animator>();
        var animatorController = _animator.runtimeAnimatorController as AnimatorController;
        if (animatorController == null) return;
        foreach (AnimatorStateTransition transition in animatorController.layers
            .SelectMany(layer => layer.stateMachine.states.SelectMany(state => state.state.transitions)))
        {
            transition.duration = 0f;
            transition.hasExitTime = false;
        }
    }
#endif
}
2 Likes

Wait… all of these solutions that use the AnimatorController class wouldn’t work in build, though… since they are using an extension of the UnityEditor class. Right?

That’s right, but they don’t have to. OnValidate is only called in the editor, anyway. You’ll have to make sure to wrap the code in #if UNITY_EDITOR precompiler flags, though, for the build to work. I’ll edit the above snippet accordingly.

I created my own AnimatorUtil based on your codes. Thanks.

using System;
using System.Collections.Generic;
using UnityEditor.Animations;
using UnityEngine;

[Serializable]
public class TransitionSettingOverride
{
    public string name; // 状态机的名字

    public bool hasExitTime;
    public bool hasFixedDuration;
    public float duration; // percent
    public float exitTime; // percent
}

[ExecuteInEditMode]
public class AnimatorUtil : MonoBehaviour
{
    public AnimatorController anim;

    public bool hasExitTime;
    public bool hasFixedDuration;
    public float duration; // percent / in seconds if hasFixedDuration is true
    public float exitTime; // always in percent

    public List<TransitionSettingOverride> overrides;

    private void OnDisable()
    {
        var stateMachine = anim.layers[0].stateMachine;

        DfsAnimatorStateMachine(stateMachine);

        Debug.Log("<color=red>Animator Updated</color>");
    }

    void DfsAnimatorStateMachine(AnimatorStateMachine stateMachine)
    {
        var states = stateMachine.states;

        List<AnimatorStateTransition> allTransitions = new List<AnimatorStateTransition>();
        foreach (var state in states)
        {
            allTransitions.AddRange(state.state.transitions);
        }

       
        TransitionSettingOverride setting = null;
        foreach (var item in overrides)
        {
            if (stateMachine.name == item.name)
            {
                setting = item;
            }
        }

        if(setting != null)
        {
            foreach (var transition in allTransitions)
            {
                transition.hasExitTime = setting.hasExitTime;
                transition.hasFixedDuration = setting.hasFixedDuration;
                transition.duration = setting.duration;
                transition.exitTime = setting.exitTime;
            }
        }
        else
        {
            foreach (var transition in allTransitions)
            {
                transition.hasExitTime = hasExitTime;
                transition.hasFixedDuration = hasFixedDuration;
                transition.duration = duration;
                transition.exitTime = exitTime;
            }
        }
       
        Debug.Log($"Reset {allTransitions.Count} transitions in {stateMachine.name}");

        foreach (var t in stateMachine.stateMachines)
        {
            DfsAnimatorStateMachine(t.stateMachine);
        }
    }
}