Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question Programmatically change concrete animation speed

Discussion in 'Animation' started by mamap, Jan 26, 2023.

  1. mamap

    mamap

    Joined:
    Aug 25, 2013
    Posts:
    8
    There is the one way to set concrete animation speed with parameters in editor:

    upload_2023-1-26_18-19-3.png

    But this way requires for manually adding every parameter for every animation state. Also manually adding the parameter to the StateMachine (in editor).
    But what if I want to change this dynamically? Set concrete AnimatorState speed or Motion time, based on inner code logic?

    I found the only one way to do it: with the AnimatorController.

    Code (CSharp):
    1. Animator.Play(pending.StateName, -1, 0f);
    2. var controller = (AnimatorController)Animator.runtimeAnimatorController;
    3. var clip = controller.animationClips.FirstOrDefault(c => c.name == pending.StateName);
    4. var unityDuration = clip.length;
    5. var speed = clip.length / pending.DurationTime;
    6. var allAnimatorStates = controller.layers.SelectMany(l => l.stateMachine.states);
    7. var animatorState = allAnimatorStates.FirstOrDefault(s=>s.state.name == pending.StateName);
    8. animatorState.state.speed = speed;
    But this also affects AnimatorController in editor when I run the game!
    Better way is to create programmatically parameters and change them in Animator, but this will also affects Animator in editor every time I will run the game.

    Is there better way to set concrete animatorState speed in runtime without change Animator in editor?
    Or to keep editor unchanged when AnimatorController StateMachine changes in runtime?
     
  2. mamap

    mamap

    Joined:
    Aug 25, 2013
    Posts:
    8
    This is code for runtime parameters generation.
    Code (CSharp):
    1. //pending = (string StateName, float: DurationTime)
    2. var controller = (AnimatorController)Animator.runtimeAnimatorController;
    3. var clip = controller.animationClips.FirstOrDefault(c => c.name == pending.StateName);
    4. var unityDuration = clip.length;
    5. var speed = clip.length / pending.DurationTime;
    6. var allAnimatorStates = controller.layers.SelectMany(l => l.stateMachine.states);
    7. var animatorState = allAnimatorStates.FirstOrDefault(s => s.state.name == pending.StateName);
    8. var speedParameter = AnimationSpeedParameterPrefix + pending.StateName;
    9. if (!controller.parameters.Any(p=>p.name == speedParameter))
    10. {
    11.     controller.AddParameter(speedParameter, AnimatorControllerParameterType.Float);
    12. }
    13. animatorState.state.speedParameterActive = true;
    14. animatorState.state.speedParameter = speedParameter;
    15. Animator.SetFloat(speedParameter, speed);
    16. Animator.Play(pending.StateName, -1, 0f);