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

Syncing Sprite Animations

Discussion in 'Animation' started by Ubspy, Mar 19, 2019.

  1. Ubspy

    Ubspy

    Joined:
    Mar 19, 2019
    Posts:
    3
    I am trying to figure out how to sync up the animations of several sprites to achieve a sort of hive mind effect. I wrote a script to try and find the time left in an animation and set it to trigger the idle animation that amount of time after the hit. Unfortunately, this doesn't work. I made sure to have no transmission times.

    Here are the pictures of the transitions:
    upload_2019-3-18_19-23-0.png

    upload_2019-3-18_19-23-13.png

    And here is my code:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class InvaderController : MonoBehaviour
    6. {
    7.     public AnimationClip idleClip, hitClip;
    8.     private Animator animator;
    9.  
    10.     //private AnimationClip idleClip, hitClip;
    11.     private float idleTime, animDeltaTime;
    12.     private float hitTime, hitStartTime;
    13.  
    14.     private bool isHit = false;
    15.  
    16.     // Start is called before the first frame update
    17.     void Start()
    18.     {
    19.         // Gets animator object from thing
    20.         animator = GetComponent<Animator>();
    21.  
    22.         idleTime = idleClip.length;
    23.         hitTime = hitClip.length;
    24.     }
    25.  
    26.     // Update is called once per frame
    27.     void Update()
    28.     {
    29.         if (isHit)
    30.         {
    31.             if (Time.time - hitStartTime > animDeltaTime)
    32.             {
    33.                 animator.SetTrigger("Sync");
    34.                 isHit = false;
    35.             }
    36.         }
    37.     }
    38.  
    39.     private void OnTriggerEnter2D(Collider2D collision)
    40.     {
    41.         // If it's a player object
    42.         if (collision.tag == "Player")
    43.         {
    44.             float normalizedTime = animator.GetCurrentAnimatorStateInfo(0).normalizedTime - Mathf.Floor(animator.GetCurrentAnimatorStateInfo(0).normalizedTime);
    45.             animator.SetTrigger("Hit");
    46.             animDeltaTime = idleTime - (normalizedTime * idleTime) + hitTime;
    47.             hitStartTime = Time.time;
    48.             isHit = true;
    49.         }
    50.     }
    51. }
    Any help would be appreciated!
     
  2. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,555
    If you want the hit animation to automatically transition back to idle, just give it an exit time transition. None of that seems to have any relevance to your first sentence about syncing multiple sprites though, so I'm not sure exactly what you're trying to achieve.
     
  3. Ubspy

    Ubspy

    Joined:
    Mar 19, 2019
    Posts:
    3
    The point is that the hit animation will stop the idle animation to immediately show the hit, and because of that, when the hit animation finishes, the idle animation of the enemy that was just hit will trigger at a different time from all the others. I want to avoid this, and always have all the idle animations going at once, as if their animation loops were still all running together.
     
  4. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,555
    The only way I know of to do that in Mecanim would be to go to the Idle state and set up a parameter to control its normalized time, however that will mean you need to constantly update that parameter yourself for the animation to actually play.

    My Animancer plugin could do it very easily though (link in my signature). Whenever you play the idle animation, you could just set its state.Time = Time.timeSinceLevelLoad and it would otherwise play normally.
     
  5. Ubspy

    Ubspy

    Joined:
    Mar 19, 2019
    Posts:
    3
    I was able to fix it, my animations still had an offset, when I removed them it worked nearly perfectly. There was an additional delay so I just subtract like 0.001 from the animDeltaTime variable and it works like a charm

    New code:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class InvaderController : MonoBehaviour
    6. {
    7.     public AnimationClip idleClip, hitClip;
    8.     private Animator animator;
    9.  
    10.     //private AnimationClip idleClip, hitClip;
    11.     private float idleTime, animDeltaTime;
    12.     private float hitTime, hitStartTime;
    13.  
    14.     private bool isHit = false;
    15.  
    16.     // Start is called before the first frame update
    17.     void Start()
    18.     {
    19.         // Gets animator object from thing
    20.         animator = GetComponent<Animator>();
    21.  
    22.         idleTime = idleClip.length;
    23.         hitTime = hitClip.length;
    24.     }
    25.  
    26.     // Update is called once per frame
    27.     void Update()
    28.     {
    29.         if (isHit)
    30.         {
    31.             if (Time.time - hitStartTime > animDeltaTime)
    32.             {
    33.                 animator.SetTrigger("Sync");
    34.                 isHit = false;
    35.             }
    36.         }
    37.     }
    38.  
    39.     private void OnTriggerEnter2D(Collider2D collision)
    40.     {
    41.         // If it's a player object
    42.         if (collision.tag == "Player")
    43.         {
    44.             float normalizedTime = animator.GetCurrentAnimatorStateInfo(0).normalizedTime - Mathf.Floor(animator.GetCurrentAnimatorStateInfo(0).normalizedTime);
    45.             animator.SetTrigger("Hit");
    46.             animDeltaTime = idleTime - (normalizedTime * idleTime) - 0.001f;
    47.  
    48.             Debug.Log(normalizedTime);
    49.  
    50.             if(normalizedTime > 0.5)
    51.             {
    52.                 animDeltaTime += hitTime * 2;
    53.             }
    54.  
    55.             hitStartTime = Time.time;
    56.             isHit = true;
    57.         }
    58.     }
    59. }
    60.