Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Join us on Thursday, June 8, for a Q&A with Unity's Content Pipeline group here on the forum, and on the Unity Discord, and discuss topics around Content Build, Import Workflows, Asset Database, and Addressables!
    Dismiss Notice

Set TimelineClip.(pre|post)ExtrapolationMode from Script

Discussion in 'Timeline' started by dseyb, Jun 10, 2017.

  1. dseyb

    dseyb

    Joined:
    Jan 24, 2014
    Posts:
    9
    Hi everyone,

    I am creating TimelineClips in code via TimelineTrack.CreateDefaultClip(). I'd like to set the extrapolation modes on those clips but I cannot do that, because the setters for those are internal.
    It seems you can set it via the Inspector only because the corresponding private fields are marked with [SerializeField].
    Is there any way to set theses values that's not reflection?

    Cheers, Dario
     
  2. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    Unfortunately, no. This is an oversight in the API - we've logged it as an item to address in our product backlog.
     
  3. panta

    panta

    Joined:
    Aug 10, 2012
    Posts:
    71
    Will this feature be coming in 2018.3? It would be really nice to be able to set this from script
     
    kogtech7 likes this.
  4. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    Probably not, but we will try to bump the priority and get it for 2019.1.
     
  5. panta

    panta

    Joined:
    Aug 10, 2012
    Posts:
    71
    no worries

    if anyone needs it, here are some extension methods that will work with 2018.2 (tested in Editor and iOS):
    Code (CSharp):
    1.    
    2.     /// <summary>
    3.     /// Private field name of <see cref="TimelineClip.postExtrapolationMode"/>
    4.     /// </summary>
    5.     private static readonly string POST_EXTRAP_MODE_INTERNAL_FIELD = "m_PostExtrapolationMode";
    6.  
    7.     /// <summary>
    8.     /// Private field name of <see cref="TimelineClip.preExtrapolationMode"/>
    9.     /// </summary>
    10.     private static readonly string PRE_EXTRAP_MODE_INTERNAL_FIELD = "m_PreExtrapolationMode";
    11.  
    12.     /// <summary>
    13.     /// Private field name of the "Animation Extrapolation" duration beyond the end of the clip
    14.     /// </summary>
    15.     private static readonly string POST_EXTRAP_TIME_INTERNAL_FIELD = "m_PostExtrapolationTime";
    16.  
    17.     /// <summary>
    18.     /// Private field name of the "Animation Extrapolation" duration before the start of the clip
    19.     /// </summary>
    20.     private static readonly string PRE_EXTRAP_TIME_INTERNAL_FIELD = "m_PreExtrapolationTime";  
    21.  
    22.     /// <summary>
    23.     /// Sets the pre-extrapolation mode for a clip
    24.     /// (uses Unity 2018.2.0f2 internal methods that may break in future versions)
    25.     /// </summary>
    26.     /// <param name="clip">Clip to set the extrapolation for</param>
    27.     /// <param name="extrapolationMode">Extrapolation behaviour</param>
    28.     public static void SetPreExtrapolationMode(this TimelineClip clip, TimelineClip.ClipExtrapolation extrapolationMode)
    29.     {
    30.         clip.SetPrivateFieldValue<TimelineClip.ClipExtrapolation>(PRE_EXTRAP_MODE_INTERNAL_FIELD, extrapolationMode);
    31.     }
    32.  
    33.     /// <summary>
    34.     /// Sets the pre-extrapolation time for a clip (duration of the extrapolated portion)
    35.     /// (uses Unity 2018.2.0f2 internal methods that may break in future versions)
    36.     /// </summary>
    37.     /// <param name="clip">Clip to set the extrapolation for</param>
    38.     /// <param name="time">How long to extrapolate into the past before the clip starts</param>
    39.     public static void SetPreExtrapolationTime(this TimelineClip clip, double time)
    40.     {
    41.         clip.SetPrivateFieldValue<double>(PRE_EXTRAP_TIME_INTERNAL_FIELD, time);
    42.     }
    43.  
    44.     /// <summary>
    45.     /// Gets the pre-extrapolation time for a clip (duration of the extrapolated portion)
    46.     /// (uses Unity 2018.2.0f2 internal methods that may break in future versions)
    47.     /// </summary>
    48.     /// <param name="clip">Clip to get the extrapolation for</param>
    49.     /// <param name="time">Duration of the extrapolation into the past before the clip starts</param>
    50.     public static double GetPreExtrapolationTime(this TimelineClip clip)
    51.     {
    52.         return clip.GetPrivateFieldValue<double>(PRE_EXTRAP_TIME_INTERNAL_FIELD);
    53.     }
    54.  
    55.     /// <summary>
    56.     /// Sets the post-extrapolation mode for a clip
    57.     /// (uses Unity 2018.2.0f2 internal methods that may break in future versions)
    58.     /// </summary>
    59.     /// <param name="clip">Clip to set the extrapolation for</param>
    60.     /// <param name="extrapolationMode">Extrapolation behaviour</param>
    61.     public static void SetPostExtrapolationMode(this TimelineClip clip, TimelineClip.ClipExtrapolation extrapolationMode)
    62.     {
    63.         clip.SetPrivateFieldValue<TimelineClip.ClipExtrapolation>(POST_EXTRAP_MODE_INTERNAL_FIELD, extrapolationMode);
    64.     }
    65.  
    66.     /// <summary>
    67.     /// Sets the post-extrapolation time for a clip (duration of the extrapolated portion)
    68.     /// (uses Unity 2018.2.0f2 internal methods that may break in future versions)
    69.     /// </summary>
    70.     /// <param name="clip">Clip to set the extrapolation for</param>
    71.     /// <param name="time">How long to extrapolate into the future beyond the clip end</param>
    72.     public static void SetPostExtrapolationTime(this TimelineClip clip, double time)
    73.     {
    74.         clip.SetPrivateFieldValue<double>(POST_EXTRAP_TIME_INTERNAL_FIELD, time);
    75.     }
    76.  
    77.     /// <summary>
    78.     /// Gets the post-extrapolation time for a clip (duration of the extrapolated portion)
    79.     /// (uses Unity 2018.2.0f2 internal methods that may break in future versions)
    80.     /// </summary>
    81.     /// <param name="clip">Clip to get the extrapolation for</param>
    82.     /// <param name="time">Duration of the extrapolation into the future beyond the clip end</param>
    83.     public static double GetPostExtrapolationTime(this TimelineClip clip)
    84.     {
    85.         return clip.GetPrivateFieldValue<double>(POST_EXTRAP_TIME_INTERNAL_FIELD);
    86.     }
    87.  
    88.  
    89.  
    90.     /// <summary>
    91.     /// Returns a private Property Value from a given Object. Uses Reflection.
    92.     /// Throws a ArgumentOutOfRangeException if the Property is not found.
    93.     /// </summary>
    94.     /// <typeparam name="T">Type of the Property</typeparam>
    95.     /// <param name="obj">Object from where the Property Value is returned</param>
    96.     /// <param name="propName">Propertyname as string.</param>
    97.     /// <returns>PropertyValue</returns>
    98.     public static T GetPrivateFieldValue<T>(this object obj, string propName)
    99.     {
    100.         if (obj == null) throw new ArgumentNullException("obj");
    101.         Type t = obj.GetType();
    102.         FieldInfo fi = null;
    103.         while (fi == null && t != null)
    104.         {
    105.             fi = t.GetField(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
    106.             t = t.BaseType;
    107.         }
    108.         if (fi == null) throw new ArgumentOutOfRangeException("propName", string.Format("Field {0} was not found in Type {1}", propName, obj.GetType().FullName));
    109.         return (T)fi.GetValue(obj);
    110.     }
    111.  
    112.     /// <summary>
    113.     /// Set a private Property Value on a given Object. Uses Reflection.
    114.     /// </summary>
    115.     /// <typeparam name="T">Type of the Property</typeparam>
    116.     /// <param name="obj">Object from where the Property Value is returned</param>
    117.     /// <param name="propName">Propertyname as string.</param>
    118.     /// <param name="val">the value to set</param>
    119.     /// <exception cref="ArgumentOutOfRangeException">if the Property is not found</exception>
    120.     public static void SetPrivateFieldValue<T>(this object obj, string propName, T val)
    121.     {
    122.         if (obj == null) throw new ArgumentNullException("obj");
    123.         Type t = obj.GetType();
    124.         FieldInfo fi = null;
    125.         while (fi == null && t != null)
    126.         {
    127.             fi = t.GetField(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
    128.             t = t.BaseType;
    129.         }
    130.         if (fi == null) throw new ArgumentOutOfRangeException("propName", string.Format("Field {0} was not found in Type {1}", propName, obj.GetType().FullName));
    131.         fi.SetValue(obj, val);
    132.     }
     
  6. kogtech7

    kogtech7

    Joined:
    Jul 31, 2017
    Posts:
    10
    Seems this didn't make the cut for 2019.1. Just a hopeful bump for 2019.2!
     
  7. ShervinM

    ShervinM

    Joined:
    Sep 16, 2017
    Posts:
    64
    Any news on this? :(
     
  8. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    Sorry, not yet.
     
  9. KristofferH

    KristofferH

    Joined:
    Oct 27, 2012
    Posts:
    51
    Hey @seant_unity do you have an ETA for this? I would really need to be able to set these parameters in order to automate the setup of Timeline the way I need. Will it be in release 2019.3f?
     
  10. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    It won't be released in the version that ships with 2019.3, but it may make it into a future compatible version.

    In 2019.3, timeline has moved to being a complete package, meaning that new versions can be released independent of the editor version.

    In the meantime, you can use the solution from @panta, or just move the timeline package from the package cache into the project and make the necessary API changes. Extrapolation.CalculateExtrapolationTimes is the method we use internally.
     
  11. KristofferH

    KristofferH

    Joined:
    Oct 27, 2012
    Posts:
    51
    In case anyone else struggles to get this to work, here's how I did it using @panta's extension methods above.

    1. Create a new C# script amongst your project assets, call it TimelineExtensions.cs or something like that.
    2. Make the class static and remove the inheritance from MonoBehaviour.
    3. Add (with using) System, System.Reflection and UnityEngine.Timeline.
    4. Copy-paste all the code from panta's post (see above) in the body of your class.
    The file TimelineExtensions.cs shoul look like this:

    Code (CSharp):
    1. using System;
    2. using System.Reflection;
    3. using UnityEngine.Timeline;
    4.  
    5. public static class TimelineExtensions
    6. {
    7.     // paste all the code from @panta in here
    8. }
    Now these extension methods should be available from your TimelineClip in your code, use it something like this:

    Code (CSharp):
    1. // create a new clip on a timeline track (stored in the variable 'track' in this example)
    2. var clip = track.CreateClip<MyCustomTimelineClip>();
    3. // Set the post-extrapolation mode to 'Hold'
    4. clip.SetPostExtrapolationMode(TimelineClip.ClipExtrapolation.Hold);
     
    vonSchlank likes this.
  12. rjevans

    rjevans

    Joined:
    Sep 24, 2010
    Posts:
    24
    Still would love to see this get a proper public API someday
     
    ST_ProductVIz likes this.
  13. SwinJR

    SwinJR

    Joined:
    Oct 1, 2020
    Posts:
    3
    This is still not fixed in Unity 2022.2
    For an oversight, five years is a long time to wait on a fix.