Search Unity

animation events on last frame aren't fired in timeline when it's the last frame of the timeline

Discussion in 'Timeline' started by VoodooDetective, Dec 10, 2019.

  1. VoodooDetective

    VoodooDetective

    Joined:
    Oct 11, 2019
    Posts:
    239
    Animation events on the last frame of my animations aren't being fired when those animations are played at the end of a timeline.
     
  2. VoodooDetective

    VoodooDetective

    Joined:
    Oct 11, 2019
    Posts:
    239
    Right now the activation clip for the object with the animator is flush with the end of the animation. If I extend it one frame beyond, the animation event fires. Is this expected behavior?
     
  3. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    Yes, that is expected. Timeline is inclusive of the first frame of clips and exclusive of the last, meaning that an active clip that starts exactly at 0 and ends at exactly frame N, will be disabled at frame N.

    This is done to make sure adjacent clips have predictable behaviour, and that only one is evaluated at the frame they connect at.

    Note that timeline doesn't necessarily playback on frames, it is sampled based on the current clock, so if it lands anywhere between frame N-1 and N, the clip is evaluated.
     
  4. KristofferH

    KristofferH

    Joined:
    Oct 27, 2012
    Posts:
    52
    @seant_unity Is there a way to get around this behaviour? I really need the last frame of the first clip to be evaluated before the next clip's first frame is evaluated.
     
  5. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    @KristofferH The only workaround is to use override tracks and overlap the clips by one frame.
     
  6. tristanlbailey

    tristanlbailey

    Joined:
    Jul 14, 2016
    Posts:
    12
    I just spent over an hour to try to get a sound clip to play, one which worked fine previously. The sound was set up to play through a function in a script, but only by an event on the very last frame of an animation clip. I eventually discovered that I could get it to work by inserting a keyframe for something else (without changing anything in the keyframe) on a frame immediately after the original last frame, where the event to play the sound function was placed.

    What I don't understand is why there are three other animation clips and sound clips that I have set up in exactly the same way, that work perfectly fine, but which don't need an extra keyframe added in. The animations all have the same sample rate (bar one - not the one I was having troubles with). The sound clips all have the same loading and compression options applied. The script function is very simple, designed only to play a particular sound from an array of sounds included in the editor UI.

    I came across another post that mentioned changing a setting in the audio low pass filter, but I am not using that component anywhere in my project.

    Perhaps this is something Unity devs could look into, as it is inconsistent behaviour in the Mechanim timeline.
     
  7. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    I would strongly recommend filing a bug report with repro steps, including both functioning and non-functioning clips. We would be happy to look into and fix it, but we obviously need the appropriate context to debug it.
     
  8. glennMediaMonks

    glennMediaMonks

    Joined:
    Nov 3, 2016
    Posts:
    5
    I'll likely submit a bug report soon as this is still not working in 2020.3 version correctly.

    but in the meantime (for anyone reading this) a quick work around for this is that on the last frame you evaluate on a time which is clip length - 0.0001f

    and then evaluate again but assign a modified track with all nonclip tracks muted. that way you end up in a correct state with both the Clip tracks and Animation track being in their intended last state.

    Code (CSharp):
    1.  
    2.  
    3. _director.time = _internalTime;
    4.             _director.Evaluate();
    5.             _prevInternalTime = _internalTime;
    6.  
    7.             if (atEnd)
    8.             {
    9.                 _state = PlayState.Completed;
    10.  
    11.                 var asset = _director.playableAsset as TimelineAsset;
    12.                 DisableClipTracks(ref asset);
    13.  
    14.                 // Bug fix
    15.                 // Timeline track will properly evaluate its animation track at max length
    16.                 // but it won't on clips: as they are seen as disabled on the last frame
    17.                 _director.playableAsset = asset;
    18.                 _director.time = _director.playableAsset.duration;
    19.                 _director.Evaluate();
    20.             }
    21.  
    22.     private void DisableClipTracks(ref TimelineAsset asset)
    23.     {
    24.         for (var i = 0; i < asset.rootTrackCount; i++)
    25.         {
    26.             var track = asset.GetRootTrack(i);
    27.  
    28.             // skip
    29.             if (track == null)
    30.                 continue;
    31.  
    32.             if (track.hasClips)
    33.             {
    34.                 track.muted = true;
    35.             }
    36.         }
    37.     }
    38.  
    39.  
    40.  
    41.  
     
  9. glennMediaMonks

    glennMediaMonks

    Joined:
    Nov 3, 2016
    Posts:
    5
    To elaborate the REAL reason why a timeline clip wont give you a proper state if you Evaluate() on its last frame / Length.

    Its that the timeline editor allows you to make clips which do not end on a frame but rather somewhere in-between.

    This can happen easily, without modifying the values directly, just move around the clip and or drag on its ends to change the length of it.

    In this example the Timeline asset has a length of a flat 5 seconds, yet 2 clips have a length of 4.99999 by just dragging them around.

    This has to then be fixed manually as you can't directly set the End value of clips by code. This prevents a programmatic solution as rounding errors on the start and duration of the clip will still occur.

    upload_2021-5-4_17-13-40.png
     
    emredesu likes this.