Search Unity

Animator, and update timing?

Discussion in 'Scripting' started by Nanako, May 28, 2015.

  1. Nanako

    Nanako

    Joined:
    Sep 24, 2014
    Posts:
    1,047
    Ok here's my situation. Every frame in Update() i'm reading the current animation time from the animator, and telling it to play an animation state if the time is less than a certain value.

    The purpose of this, what i intend to do, is to skip the first frame of a looping animation by constantly setting it forward to at least the second frame if its less than that (i do some calculations with time)

    It's not quite working, and i tried slowing the timescale way down to figure out why. What seems to be happening is that after a cycle through the loop, the animator goes back to the first frame, and renders it, before my code is called, resulting in the start of the animation being shown for one game frame before my code sets it forward. This is not good enough

    Possibly related:
    What does this function do? the documentation is worthless http://docs.unity3d.com/ScriptReference/Animator.Update.html

    Anyways, what i hope to find, is some way to preempt this. Is there any way i can call code at the start of a frame, before other things are processed or rendered? Update seems to be doing it at the end. Animator.Update sounds a lot like the update monobehaviour, but is it actually related ?
     
    Last edited: May 28, 2015
  2. Nanako

    Nanako

    Joined:
    Sep 24, 2014
    Posts:
    1,047
    A little more info.

    Here i'm using a debug setting of jumping 10 frames forward, just to make things more visible. This is roughly halfway through the animation. So what i'd expect to happen is that the progress bar hits the end, and then jumps back to the middle, and continues from there. But here's what i actually see (Timescale slowed down to 0.1)




    As can be seen, for a brief period the animation shows at the start, before jumping to the halfway-ish point.

    Here's the code i'm using, this function is called in Update()

    Code (CSharp):
    1.     void AdditiveAnimFix()
    2.     {
    3.         float skiptime = 0.09f;
    4.         float timeMult = 10f;
    5.         a = anim.GetCurrentAnimatorStateInfo(1);
    6.         b = anim.GetCurrentAnimatorClipInfo(1);
    7.         if (b.Length > 0)
    8.         {
    9.             c = b[0].clip;
    10.  
    11.             float normalizedSkipTime = (1f / c.frameRate) * timeMult;
    12.             if (a.normalizedTime % 1 < normalizedSkipTime)
    13.             {
    14.                 print("FirstFrame =" + normalizedSkipTime);
    15.                 anim.Play(a.shortNameHash, 1, normalizedSkipTime);
    16.             }
    17.         }
    18.         previousVelocity = body.velocity;
    19.     }
    TimeMult is a debug value that basically says how many frames from the start, to jump to. The rest of the code calculates the duration of one frame, multiplies it by timeMult, and restarts the animation at that time point.

    It's clearly working. It's just not working fast enough.
     
  3. Nanako

    Nanako

    Joined:
    Sep 24, 2014
    Posts:
    1,047
    any advice at all? x
     
  4. Trigve

    Trigve

    Joined:
    Mar 17, 2013
    Posts:
    139
    Maybe you could use Animator.Update(). I'm using it to update animation manually for each frame.

    I set the speed of the animation to 0 as a default. Then when I want to update animation I set it to for instance 1, call the Animator.Update() and then set it to the 0 back.

    In your case you'll do the same but before setting the speed to 0, you would need to put this logic finding if you've looped your animation. and if yes, set the appropriate time and call the Animator.Update() once more.

    Edit: Or you can try to put your code in LateUpdate()
     
  5. eisenpony

    eisenpony

    Joined:
    May 8, 2015
    Posts:
    974
    I don't think your calculation of normalizedSkipTime is correct. As best I can tell, this formula is finding the number of seconds at which the tenth frame occurs. I think you need to divide by the length of the animation to normalize it.
     
    Nanako likes this.
  6. Nanako

    Nanako

    Joined:
    Sep 24, 2014
    Posts:
    1,047
    thank you! this has worked utterly perfectly.
    @eisenpony : thanks for that, i made a math error.

    Here's my code now, and this works flawlessly:

    Code (CSharp):
    1.     void AdditiveAnimFix()
    2.     {
    3.         float skiptime;
    4.         float timeMult = 2f;
    5.         a = anim.GetCurrentAnimatorStateInfo(1);
    6.         b = anim.GetCurrentAnimatorClipInfo(1);
    7.         if (b.Length > 0)
    8.         {
    9.             c = b[0].clip;
    10.  
    11.             float normalizedSkipTime = (1f / c.frameRate) * timeMult;
    12.             normalizedSkipTime /= c.length;
    13.             if (a.normalizedTime % 1 < normalizedSkipTime)
    14.             {
    15.                 //print("FirstFrame =" + normalizedSkipTime);
    16.                 anim.Play(a.shortNameHash, 1, normalizedSkipTime);
    17.                 anim.Update(Time.deltaTime);
    18.             }
    19.         }
    20.         previousVelocity = body.velocity;
    21.        
    22.     }