Search Unity

Sync Animations on multiple objects

Discussion in 'Animation' started by shaunharwood, Sep 8, 2016.

  1. shaunharwood

    shaunharwood

    Joined:
    Sep 8, 2016
    Posts:
    2
    What is the best way to sync identical animations on two objects?. I have two buttons attached to a canvas – I set an animation controller up on each button with animations to slide the buttons on and off the screen based on the state of a parameter. Then - in a script - during the update I have something like the following:

    Public Animator button1;
    Public Animator button2

    Void Update()
    {

    If( something happens)
    {
    Button1.setbool(“Parameter Name”, true);
    Button2.setbool(“Parameter Name”, true);
    }

    Something Else happens
    {
    Button1.setbool(“Parameter Name”, false);
    Button2.setbool(“Parameter Name”, false);
    }

    State machine and transitions for each controller then make everything move.

    Here’s the effect I am trying to correct. The two animations are not synchronized. Sometimes buttons 1 & 2 move perfectly together – sometimes 1 ahead of 2 and some times 2 ahead of 3 – all very random.

    What is the best technique for synchronizing identical animations on different objects (more than 2) so that everything moves ‘together’?

    Appreciate any guidance – have tried searching for this but I am not sure if incorrect terminology is the reason I am not finding much.
     
    Siggytron likes this.
  2. shaunharwood

    shaunharwood

    Joined:
    Sep 8, 2016
    Posts:
    2
    victormaurer1 and Siggytron like this.
  3. bennichols23

    bennichols23

    Joined:
    Jun 15, 2016
    Posts:
    1
    Hey! Thought I'd just pop in and give everyone a more in-depth solution. I was having a lot of troubles with this for some reason, but using the idea from that link managed to solve the issue. The issue I had was whenever I was trying to grab the AnimationStateInfo, it was either returning null or 0 (I'm sure I was missing something obvious that would've fixed this)

    Anyways, like in that other post, the idea is to throw down an animator on your scene to act as the parent for all other animations that are instantiated after the scene has started.

    Code (CSharp):
    1. protected Animator Animsync;
    2. protected Animator Animation;
    3.  
    4. private void Awake()
    5. {
    6.     Animsync = GameObject.Find("Animsync").GetComponent<Animator>();
    7.     Animation = GetComponent<Animator>();
    8. }
    9.  
    10. private void Update()
    11. {
    12.     Animation.Play(0, -1, Animsync.GetCurrentAnimatorStateInfo(0).normalizedTime);
    13. }
    The idea is your find a master animator (I called it Animsync), get it's animator state info, and then return the normalized time of that animation. From there, you just update your animation in an Update() event. (so you'd attached this C# script to every game object with an Animator component on it that you want to be synced)

    Hopefully this helps you as I was stuck on this for the longest time!
     
  4. customphase

    customphase

    Joined:
    Aug 19, 2012
    Posts:
    246
    Heres slightly modified version of the same approach, that supports sub-states syncing, as well as multiple layers with different weights:

    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.     }
     
    trombonaut and RodrigoSeVeN like this.
  5. lacas8282

    lacas8282

    Joined:
    Apr 25, 2015
    Posts:
    139
    This not syncing the transitions guys. :(
     
  6. lacas8282

    lacas8282

    Joined:
    Apr 25, 2015
    Posts:
    139

    This not syncing the transitions guys.
     
  7. mvqq

    mvqq

    Joined:
    Feb 3, 2019
    Posts:
    4
    To sync identical Animations in a clean way, create a StateMachineBehaviour script named whatever you want and a Parameter named "Offset" in your Animator Controller.

    Choose one of the Animations to be the one the others should be syncronized to.

    Then, set the Cycle Offset to be equal to the Offset paramete on the animations you chose.
    upload_2023-7-28_6-16-32.png

    Then, add the StateMachineBehaviour script to the animations you chose with the "OnStateEnter" method as such:

    Code (CSharp):
    1.         override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    2.     {
    3.                 var animsync = GameObject.Find("Animsync").GetComponent<Animator>();
    4.                 animator.SetFloat("Offset", animsync.GetCurrentAnimatorStateInfo(0).normalizedTime % 1);
    5.         }
    This will accurately update the Cycle Offset to be equal to where your main Animation is currently at during its animation, and doesn't solve the problem by just spamming the Update() method.