Search Unity

  1. Are you interested in providing feedback directly to Unity teams? Sign up to become a member of Unity Pulse, our new product feedback and research community.
    Dismiss Notice

How to Sync three animations

Discussion in 'Animation' started by AaronC, Jun 10, 2015.

  1. AaronC

    AaronC

    Joined:
    Mar 6, 2006
    Posts:
    3,553
    I have three synchronised animations in three files, and I play them in sync at the start of the scene and then also later in the scene. However I can't seem to get them to sync in the later stage.

    My transitions throughout are all triggers, and each has its own controller. I tried the .animator.ResetTrigger("myTriggerNames") approach on all three. Even after immediately calling the Reset trigger and then triggering the desired animations on all three objects, I sill have them way out of sync. Anyone have any "one size fits all" objective advice for getting them in sync?

    Thanks
     
  2. Mecanim-Dev

    Mecanim-Dev

    Unity Technologies

    Joined:
    Nov 26, 2012
    Posts:
    1,674
    You can always force a sync by calling Animator.Play(0,-1, currentTime);
    Using 0 as the first parameter tell the animator to change the time of the current state without triggering OnStateEnter.
    The idea is to have a master animator, which you can poll the current state time and use it to drive the two slave animator.

    Or you could try to trigger the tree animation togheter from the same Update function with

    Code (CSharp):
    1.  
    2. void Update()
    3. {
    4.     if(startSyncAnim)
    5.     {
    6.         Animator1.Play(myfirstanimstate,-1, 0);
    7.         Animator2.Play(mysecondanimstate,-1, 0);
    8.         Animator3.Play(mythridanimstate,-1, 0);
    9.     }
    10. }
     
  3. AaronC

    AaronC

    Joined:
    Mar 6, 2006
    Posts:
    3,553
    Thanks thats done the trick!
     
  4. Siggytron

    Siggytron

    Joined:
    Feb 9, 2018
    Posts:
    12

    This helped me in 2019!

    I think most of the time, using transition in the animator would probably be fine but for synchronizing animations to start on 2 (or more) objects at once, the animator.Play method worked so much better for me. Thank you.
     
    Malbers likes this.
  5. Serinx

    Serinx

    Joined:
    Mar 31, 2014
    Posts:
    760
    I found this post when searching for my problem and it's sort of relevant. I wanted my animators to always be in sync. So every time I set an animator parameter, I want multiple animators to receive the same parameter value.
    I created this simple script called AnimatorSynchroniser which you can attach to your gameobject. In your scripts, instead of referencing the Animator component, reference the AnimatorSynchroniser and you can set your parameters for all the Animators in 1 call.

    example:
    Code (CSharp):
    1. GetComponent<AnimatorSynchroniser>().SetFloat("speed", 2f);
    It's pretty basic atm, but it can easy be extended just by creating a wrapper for the different animator functions like I've done already.

    Hopefully this helps someone!

    AnimatorSynchroniser.cs
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class AnimatorSynchroniser : MonoBehaviour
    4. {
    5.     public Animator[] animators;
    6.  
    7.     private void Start()
    8.     {
    9.         //Assumes all Animator components are children
    10.         //You can change this or remove this line and assign your animators in the inspector
    11.         animators = GetComponentsInChildren<Animator>();
    12.     }
    13.  
    14.     //Set a boolean parameter for all animators
    15.     public void SetBool(string name, bool value)
    16.     {
    17.         foreach (Animator anim in animators)
    18.         {
    19.             anim.SetBool(name, value);
    20.         }
    21.     }
    22.     //Set a float parameter for all animators
    23.     public void SetFloat(string name, float value)
    24.     {
    25.         foreach (Animator anim in animators)
    26.         {
    27.             anim.SetFloat(name, value);
    28.         }
    29.     }
    30.     //Set an integer parameter for all animators
    31.     public void SetInteger(string name, int value)
    32.     {
    33.         foreach (Animator anim in animators)
    34.         {
    35.             anim.SetInteger(name, value);
    36.         }
    37.     }
    38.     //Set a trigger parameter for all animators
    39.     public void SetTrigger(string name)
    40.     {
    41.         foreach (Animator anim in animators)
    42.         {
    43.             anim.SetTrigger(name);
    44.         }
    45.     }
    46.  
    47.     //The get functions just return the first animators value - no point looping here
    48.     public bool GetBool(string name)
    49.     {
    50.         return animators[0].GetBool(name);
    51.     }
    52.  
    53.     public float GetFloat(string name)
    54.     {
    55.         return animators[0].GetFloat(name);
    56.     }
    57.  
    58.     public int GetInteger(string name)
    59.     {
    60.         return animators[0].GetInteger(name);
    61.     }
    62. }
     
  6. LeandroExHuMeD

    LeandroExHuMeD

    Joined:
    Apr 6, 2016
    Posts:
    5
    I tried to use this same approach of playing the animation on Update but still not works. Is there another solution? One of my animations is always some frames forward than the other no matter what I do or how I call them.
     
  7. Emery-Monzerol

    Emery-Monzerol

    Joined:
    Nov 1, 2012
    Posts:
    17
    Still having this problem in 2019.4.11f1.

    I've been trying to set up two separate Game Objects each with an Animator component, both using a different Animator Controller Override based on the exact same Animator Controller. The Controller has multiple layers, including an additive layer. All the parameters sent to both animators are always being sent at the exact same frame.

    I have tried the solutions listed above, and multiple variants (notably: using CrossFade, iterating through the layers to call Play() on each layer, calling Update(0f) on the animators every frame after these modifications). Nothing I do seems to work, there's always a slight delay between both animators.
     
  8. customphase

    customphase

    Joined:
    Aug 19, 2012
    Posts:
    231
    This is great, but doesnt work well with sub-states, the state inside the sub-state remains unsynced. Is there a way to force a sync on sub-states as well?

    Nvm, figured it out pretty much right away :) Shouldnt use 0 as a first parameter, but should instead use the master's current state hash, i.e.

    Code (CSharp):
    1.     void Update()
    2.     {
    3.         for (int i = 0; i < toAnim.layerCount; i++)
    4.         {
    5.             toAnim.Play(fromAnim.GetCurrentAnimatorStateInfo(i).fullPathHash, i, fromAnim.GetCurrentAnimatorStateInfo(i).normalizedTime);
    6.             toAnim.SetLayerWeight(i, fromAnim.GetLayerWeight(i));
    7.         }
    8.     }
    Actually, theres another problem, is that this approach doesnt support transition blending. How do we fix that?
     
    Last edited: Feb 3, 2021
  9. marchall_box

    marchall_box

    Joined:
    Mar 28, 2013
    Posts:
    85
unityunity