Search Unity

How to make custom playables reset to previous state after preview

Discussion in 'Timeline' started by Yukken, Apr 24, 2019.

  1. Yukken

    Yukken

    Joined:
    Jul 12, 2015
    Posts:
    93
    I made a custom playable that advances the dialogue once per clip.When I preview the timeline in edit mode, it works but the changes persist after exiting preview. Is this expected behavior? If not, How to fix it so that the state of the dialogue track is reset when preview ends?

    Here is the behaviour class for the clip. It simply calls a function to advance the text on the linesource once in it' lifetime.
    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3. using UnityEngine.Playables;
    4. using UnityEngine.Timeline;
    5.  
    6. [Serializable]
    7. public class DialogueTrackBehaviour : PlayableBehaviour
    8. {
    9.     bool hasBegun = false;
    10.  
    11.     public override void OnPlayableCreate(Playable playable)
    12.     {
    13.  
    14.     }
    15.  
    16.     public override void ProcessFrame(Playable playable, FrameData info, object playerData)
    17.     {
    18.         if (!hasBegun)
    19.         {
    20.             LineStream lineSource = playerData as LineStream;
    21.             hasBegun = true;
    22.             lineSource.advanceText();
    23.         }
    24.     }
    25. }
    26.  
     
  2. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    You can tell timeline which properties you intend to modify using the IPropertyPreview interface.

    For example:
    Code (CSharp):
    1. public class TestCustomClip : PlayableAsset, IPropertyPreview
    2. {
    3.     ....
    4.     public void GatherProperties(PlayableDirector director, IPropertyCollector driver)
    5.     {
    6.         const string kLocalPosition = "m_LocalPosition";
    7.         const string kLocalRotation = "m_LocalRotation";
    8.  
    9.         driver.AddFromName<Transform>(kLocalPosition + ".x");
    10.         driver.AddFromName<Transform>(kLocalPosition + ".y");
    11.         driver.AddFromName<Transform>(kLocalPosition + ".z");
    12.         driver.AddFromName<Transform>(kLocalRotation + ".x");
    13.         driver.AddFromName<Transform>(kLocalRotation + ".y");
    14.         driver.AddFromName<Transform>(kLocalRotation + ".z");
    15.         driver.AddFromName<Transform>(kLocalRotation + ".w");
    16.     }
    17.     ...
    18. }
    In your case, driver.AddFromName<LineStream>("variableName"); where variableName is the name of the serialized property (i.e. the field) in the LineStream that is being modified by advanceText();
     
    florianBrn likes this.
  3. Yukken

    Yukken

    Joined:
    Jul 12, 2015
    Posts:
    93
    Uh I'm not very familar with reflection. I just used the playabes wizard to generate most of the code and modified it to my understanding. In my case advancetext() does not directly modify properties of line stream. The linestream class has a list of strings for dialogue, an int field for index and a text gameobject ref. The advancetext() function increments the index and sets the text to the next string in the list.
    Is this incompatible with playables?
     
    Last edited: Apr 24, 2019
  4. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    No reflection required. Which ever fields in the monobehaviour are serialized.

    e.g. if your class looks like this

    public class SampleMonoBehaviour : Monobehaviour
    {
    public int index;
    public string text;
    ....

    }

    Your GatherProperties code would be
    ...
    driver.AddFromName<SampleMonoBehaviour>("index");
    driver.AddFromName<SampleMonoBehaviour>("text");

    It does get more complicated when you target built-in Unity Components, but for your own Monobehaviours, it is pretty straight forward.
     
    koirat likes this.
  5. Yukken

    Yukken

    Joined:
    Jul 12, 2015
    Posts:
    93
    Does a textmeshpro field count as built in unity component?
     
  6. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    If the field exists in your monobehaviour, you can just use the name of the field without a problem even if it refers to a Unity type.

    The only time it gets tricky is when your track binds to a Unity Type (TextMeshPro might count here) because it's tricky to know which of it's fields are actually serialized, or what their names are.
     
  7. koirat

    koirat

    Joined:
    Jul 7, 2012
    Posts:
    2,073
    I just had this problem.

    At first I have tried:
    driver.AddFromName<Light>(nameof(Light.color))
    (obviously is is not working)

    Than I changed inspector mode to debug and when you hover over the light color label it displays the property name"
    driver.AddFromName<Light>("m_Color")

    Still it would be good to have library of property names instead of hard coded strings.



    Now my question is it possible to have similar functionality at run time.
    So when timeline finished playing my property is restored ?
     
    florianBrn likes this.
  8. ggevrin

    ggevrin

    Joined:
    Jan 8, 2013
    Posts:
    13
    Sorry to dig out an old post but I cannot find a satisfying answer. I wanted to use GatherProperties method from a custom timeline track to undo what is previewed in the timeline window. Works fine for transform properties like localPosition but what about parenting ? I cannot undo the parenting this way, the serialized property m_Father cannot be used by the driver.
    Code (CSharp):
    1. serializedObject.FindProperty("m_Father")
    works fine and retrieves this property but if I try to use this propertyname with
    Code (CSharp):
    1. driver.AddFromName<Transform>(goTargetExposed, "m_Father");
    I have an error (works fine for properties like m_LocalPosition.x)
    upload_2023-8-21_13-44-8.png
    What I am attempting to achieve is : I have a timeline, it is changing parenting of an object. I want to be able to preview this timeline and its effects without playing (no problem for this) but I want also to rollback the timeline changes while leaving the Preview mode. The IPropertyPreview interface looked perfect for this but I cannot manage to undo parenting changes (yes I had a look at https://docs.unity3d.com/ScriptReference/Undo.SetTransformParent.html, it works fine but it is not automatically invoked when leaving the preview mode, unlike the properties modifications gathered by IPropertyPreview). I did not manage to find any hook for entering/leaving the preview mode either (yes I can code it myself by watching the timeline window on each frame but it's kinda clunky)...
    Does anyone have an advice please ?
     
    Last edited: Aug 22, 2023