Search Unity

Assign exposed variable in runtime

Discussion in 'Timeline' started by Xaon, Dec 6, 2017.

  1. Xaon

    Xaon

    Joined:
    Feb 28, 2013
    Posts:
    62
    I have a case where I have one player character object instance that is used across couple of additively loaded scenes. Right now Timelines exposed variables doesn't work with multi scene setup. But event if it did I'ld like to make my player character object be spawned dynamicaly at the begining of gamaplay insted of having it sitting on a specific scene.
    To achieve what I need I could recreate the AnimationTrack so it would find reference when it starts playing. But I haven't found source code for the AnimationTrack and I would probably recreate it poorly.
    Second option is use a proxy object when setting up timeline and change it on runtime. But I see only "get" method avaible ( PlayableDirector.GetGenericBinding ). And even if this get method is the way to go I cannot figure it out.

    I would apreciate help with any of the two approaches.
     
  2. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    If I understand correctly, you are trying to bind a track to a dynamically spawned object.

    You can use PlayableDirector.SetGenericBinding(track, gameObject), and get the track by either searching through the timeline, or by searching through the bindings:

    Here's an example that shows both methods (attached to the dynamically spawned object):

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Timeline;
    5. using UnityEngine.Playables;
    6.  
    7. public class DynamicBind : MonoBehaviour {
    8.  
    9.     public string trackName = "MyCharacterTrack";
    10.  
    11.     // Use this for initialization
    12.     void Start () {
    13.  
    14.         var animator = GetComponent<Animator>();
    15.         var playableDirectors = FindObjectsOfType<PlayableDirector>();
    16.         foreach (var director in playableDirectors)
    17.         {
    18.             // method 1, using generic playable assets
    19.             if (director.playableAsset != null)
    20.             {
    21.                 foreach (var binding in director.playableAsset.outputs)
    22.                 {
    23.                     if (binding.streamName == trackName)
    24.                         director.SetGenericBinding(binding.sourceObject, animator);
    25.                 }
    26.             }
    27.             // method2, using timeline
    28.             var timelineAsset = director.playableAsset as TimelineAsset;
    29.             if (timelineAsset != null)
    30.             {
    31.                 foreach (var track in timelineAsset.GetOutputTracks()
    32.                 {
    33.                     if (track is AnimationTrack && track.name == trackName)
    34.                         director.SetGenericBinding(track, animator);
    35.                 }
    36.             }
    37.         }
    38.     }
    39. }
    40.  
     
    amesa_unity likes this.
  3. Xaon

    Xaon

    Joined:
    Feb 28, 2013
    Posts:
    62
    Thanks @seant_unity ! It works! Not I understand. Using method 1 I have to gather all tracks with director.playableAsset.outputs, then I use reference to a track to get binding object with director.GetGenericBinding. Then I check if GetGenericBinding returned my proxy object. If so I replace it with SetGenericBinding.
    It seams there's a lot going on under the hood in Timeline and it's hard to get a head around all those classes ;)
     
  4. FeastSC2

    FeastSC2

    Joined:
    Sep 30, 2016
    Posts:
    978
    It works indeed but the track name is something most tracks don't have like an AnimatorTrack or CinemachineTrack.

    How to rebind a specific AnimatorTrack for example?
     
    dbdenny likes this.
  5. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    The track name can be assigned in the inspector for the track. If a track has a binding, it shows that instead of the name, but the name still exists.