Search Unity

Resolved Editor Script for detecting new keyframe and automate add signal event

Discussion in 'Timeline' started by darreney, Oct 13, 2020.

  1. darreney

    darreney

    Joined:
    Oct 9, 2018
    Posts:
    34
    Hi,
    i'm trying to use timeline as a beatmap editor for a rhythm game like Osu!. It involves having hundreds of beat graphics, that will be designed to appear at specific positions at specific timings along the timeline. This video gives an idea what a beatmap editor is:


    i'm trying out this workflow to use 1 animation track to manage all the beats, by adding keyframes to represent a new beat at a new position. However, this will also require spawning a new object at each keyframe, meaning having to add a signal event on top of each keyframe to call a function to spawn the object. So the steps will be create a keyframe + a signal for each beat, and make sure they are at the exact same timing.

    I'm hoping to have a workflow that is easy for editing the beatmap, so that the level designer can just focus on designing the level without much unnecessary steps.
    So, i'm interested to find out if there is any way that i can do some editor scripting to detect when a new keyframe is added, and then automate the add signal event?
    Or if you have other suggestions to approach this beatmap editor at all, i'd like to know too!
    Any help is appreciated. Thanks!
     
  2. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    It sounds like you may want to consider creating a custom track to help you out. Here are some random thoughts which may or not help in this regard.

    1. You can animate parameters on a track (like to the audio track volume), but you will lose the dopesheet markers that the animation track has. If they are a requirement, you can use a TrackEditor to autogenerate custom markers at the beat points.
    2. Using clips instead of tracks will let you animate clip parameters & draw on the clip background using a ClipEditor.
    3. Timeline 1.4 introduces Actions. Actions lets you add custom menu items to tracks, clips, etc....They can be used to create new actions used by designers to do things like automating tracks keys to signals conversion.
    4. Tracks and clips can also send signals from their PrepareFrame and ProcessFrame PlayableBehaviour methods. The FrameInfo contains a PlayableOutput, which exposes PushNotification. SignalEmitters implement INotification, but you can also create your own notifications and NotificationReceivers.
     
  3. darreney

    darreney

    Joined:
    Oct 9, 2018
    Posts:
    34
    Thank you for the reply @seant_unity !

    i am indeed already using Clips as you suggested in #2.

    I've actually managed to come up with a method with editor script.
    It's nothing to do with timeline at all, but using AnimationUtility to create events for each key. And i figured i don't need to add together with a new keyframe. I can use a MenuItem or hotkey to add all the events at one go after all the keyframes are done manually.
     
  4. darreney

    darreney

    Joined:
    Oct 9, 2018
    Posts:
    34
    oh wait, i'm stuck yet again, i tried to use AnimationUtility to get the clips from a gameobject, but the clips count is 0.
    Code (CSharp):
    1. AnimationClip[] clips = AnimationUtility.GetAnimationClips(gameObject);
    i suppose i should get the clip from the timeline instead of getting from the gameobject. I saw a code doing this but it seems Unity 2019 no longer use these methods.
    https://answers.unity.com/questions/1516901/how-to-get-the-track-and-the-clip-of-a-timeline.html

    @seant_unity may i know what is the correct way in Unity 2019 for retrieving the AnimationClipPlayable from timeline? So that i can have access to the clip to call AnimationUtility.GetCurveBindings(clip).


    EDIT:
    Sorry, i may be confused, what i'm using might not be Clips, cos when i click "convert to clip track" it will look different. I am currently using the 'Edit in animation window', and i can see the keyframes within the track that reflects whatever i've edited. (Sorry not able to upload picture here).

    I am currently using the AnimationUtility.onCurveWasModified delegate function to add events for ALL keys when one key is edited (which i thought it's overkill, hence i'm enquiring about the above).
    i realize when i called AnimationUtility.GetAnimatedObject, the returned object is actually the timeline object and not the 'beat' gameobject (bound to the animation track) that i am animating the position.
     
    Last edited: Oct 14, 2020
  5. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    If you need the animation clip from an infinite mode track, use AnimationTrack.infiniteClip. If it's converted to a clip track, then ((AnimationPlayableAsset) (animationTrack.GetClips().First().asset)).clip will give you the animation clip.

    To get the animator itself, you need to retrieve that from the playable director - playableDirector.GetGenericBinding(animationTrack) as Animator.

    I hope that helps.
     
  6. darreney

    darreney

    Joined:
    Oct 9, 2018
    Posts:
    34
    Ah i totally missed out looking at the Timeline api, and i was struggling to make sense of the code that i linked previously while only looking at the Playables api and getting nowhere . So the key is to cast PlayableDirector.playableAsset as TimelineAsset.

    And yes, thanks for pointing out about infiniteClip, that is what works for me.
    I have got it all set now thank you @seant_unity !
     
    Last edited: Oct 14, 2020