Search Unity

Set ExposedReference<T> Value

Discussion in 'Timeline' started by David-J-Foster, May 14, 2017.

  1. David-J-Foster

    David-J-Foster

    Joined:
    Jan 13, 2014
    Posts:
    18
    I have a PlayableBehaviour which has a serialised ExposedRerence<Component> field. I have a PlayableTrack which checks its timeline clips and if it encounters a clip whose asset is a game object (after dragging and dropping a game object on the track), it removes the clip and creates a new PlayableBehaviour timeline clip instead.

    That's all fine, but what I need to do is grab a component on the previously mentioned game object and assign the newly created PlayableBehaviour's ExposedRerence<Component> field to this component.

    How do I do this?

    One thing I have tried which failed is to get the resolver on the current graph and set its reference value using IExposedPropertyTable.SetReferenceValue. If I then check that I was successful with GetReferenceValue, I see that I am indeed setting it, but nothing is updating in the editor. Am I working on the wrong graph? Or is this approach fundamentally misguided? Any help at all is mightily appreciated.
     
  2. julienb

    julienb

    Unity Technologies

    Joined:
    Sep 9, 2016
    Posts:
    177
    The following PlayableBehaviour will create a new GameObject and set it to the graph's resolver. If you use the exposedReference's exposedName when calling SetReferenceValue, it should work. Let me know if this fixes your issue.

    Code (CSharp):
    1. public class TestPlayable : BasicPlayableBehaviour {
    2.  
    3.     [SerializeField] public ExposedReference<GameObject> reference;
    4.  
    5.     public override void OnPlayableCreate(Playable playable)
    6.     {
    7.         GameObject plane = GameObject.CreatePrimitive(PrimitiveType.Plane);
    8.         plane.name = "TestGO";
    9.         playable.GetGraph().GetResolver().SetReferenceValue(reference.exposedName, plane);
    10.     }
    11. }
     
    mandisaw likes this.
  3. David-J-Foster

    David-J-Foster

    Joined:
    Jan 13, 2014
    Posts:
    18
    That sneaky exposedName property was definitely what I needed! Can't believe I missed that. Thanks a bunch!

    Now that the assignment is working, I have discovered another small issue which I hope you could point me in the right direction on?

    I think I might be doing things a bit differently (or maybe incorrectly) for the following reasons:
    1. What is BasicPlayableBehaviour? I've seen this multiple times and don't know how people have access to it.
    2. I can't think of a use case where having an exposed reference on a playable behaviour will be useful. Maybe I'm lacking in imagination! Wouldn't it make more sense to have a playable asset have an exposed reference because at least then we have access to it in the editor to assign scene references.

    Following on from point 2, I have this situation:
    1. I have a CustomPlayableTrack which, on CreateTrackMixer, uses CreateDefaultClip to instantiate a CustomPlayableAsset. I then call an init method on this playable asset which passes through an object reference and the graph reference received with CreateTrackMixer.
    2. The playable asset then uses the given graph from the track to update an ExposedReference value with the given object reference.
    3. The playable asset then receives a call to CreatePlayable, where it resolves the previously set exposed reference on the graph received through CreatePlayable. It instantiates a ScriptPlayable<CustomPlayableBehaviour> and passes through the resolved reference.

    This actually all works now given use of exposedName. However, whenever I perform the above more than once, all assets on the track have their references updated with the latest object.

    I think this is to do with using the track's graph to set the reference value on my CustomPlayableAssets. How would I go about setting the reference value on my CustomPlayableAsset when I don't have access to a graph? Note that this happens before the call to my asset's CreatePlayable method, which typically passes the correct graph.
     
  4. julienb

    julienb

    Unity Technologies

    Joined:
    Sep 9, 2016
    Posts:
    177
    A BasicPlayableBehaviour combines both a PlayableAsset and a PlayableBehaviour. It is meant to simplify things and avoid users having to create two classes. It is also simpler when writing examples ;) Having a PlayableAsset/PlayableBehaviour pair is the preferred way, since a BasicPlayableBehaviour is more costly on performance.

    You are right that, on a PlayableBehaviour, an exposed reference doesn’t make any sense. The exposed references normally go into a PlayableAsset. See it like this: the PlayableAsset contains the data necessary for your PlayableBehaviour to function as the PlayableAsset is used to create the PlayableBehaviour. That’s why they normally they come in pairs.

    As for your CustomPlayableAsset and exposed properties issue, could you post a sample of your code? There are many moving parts here and having the code could help me find what’s happening.
     
    Last edited: Jun 6, 2017
  5. C10110

    C10110

    Joined:
    Jan 19, 2013
    Posts:
    58
    Hey guys!

    I am having a similar issue. In Beta1 of 2017 I was able to create a playbleasset and playable behavior (when they were two separate scripts)

    Now, having upgraded to a more recent beta, it seems the api has changed, and the docs are not up to date yet.

    I was following the Beta12017 PDF to create a playable asset and behavior, however I am not sure how to do it with the new api.

    Thanks for any insight, I look forward to using Timeline!
     
  6. David-J-Foster

    David-J-Foster

    Joined:
    Jan 13, 2014
    Posts:
    18
    Thanks for the clarification julienb. I'm glad my intuition on playable assets vs behaviours is correct.

    It will take a little time my end to extract only the relevant scripts exhibiting the behaviour, as I don't want to give you a project with masses of irrelevant complexity. I hope to find time to do that this week, and will update here with the files ASAP.

    Thanks again for your support.
     
    julienb likes this.
  7. wabugi

    wabugi

    Joined:
    Nov 4, 2014
    Posts:
    17
    thierry_unity likes this.
  8. C10110

    C10110

    Joined:
    Jan 19, 2013
    Posts:
    58
  9. HugMat

    HugMat

    Joined:
    Mar 30, 2017
    Posts:
    16
    hello guys,
    I am having kind of the same issue too, with Cinemachine :

    I am creating a default Cinemachine Shot in the Timeline, and then I want to set its VirtualCamera.
    But the field is ExposedReference, so it doesn't work...

    Any clue ?

    Thanks a lot

    Code (CSharp):
    1. internal sealed class CinemachineShotPlayable : PlayableBehaviour
    2.     {
    3.         public CinemachineVirtualCameraBase VirtualCamera;
    4.     }
    5.  
    6.     public sealed class CinemachineShot : PlayableAsset, IPropertyPreview
    7.     {
    8.         public ExposedReference<CinemachineVirtualCameraBase> VirtualCamera;
    9.  
    10.         public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
    11.         {
    12.             var playable = ScriptPlayable<CinemachineShotPlayable>.Create(graph);
    13.             playable.GetBehaviour().VirtualCamera = VirtualCamera.Resolve(graph.GetResolver());
    14.             return playable;
    15.         }
     
  10. C10110

    C10110

    Joined:
    Jan 19, 2013
    Posts:
    58
    HugMat,

    I know dude, it wasn't very intuitive for me until a friend showed me how to do it. Take a look at this screenshot:


    There is a drop down menu that lets you select the active Timeline or something. You can't seem to apply objects to Timeline scripts if you don't do this, despite the values remaining open. Hope this helps you too!!
     
  11. HugMat

    HugMat

    Joined:
    Mar 30, 2017
    Posts:
    16
    Hi Angelus1818,
    actually it's not really my problem : I can already access my timeline via script.
    The issue is that I want to create a new CinemachineShot and set its Virtual Camera but
    - I don't know how to create a Cinemachine Shot via script : the only way I found to do so is creating a default clip in the Cinemachine Track
    - When I have my Cinemachine Shot, I don't know how to set its Virtual Camera field because it is an ExposedReference...
     
    Last edited: Jul 10, 2017
  12. julienb

    julienb

    Unity Technologies

    Joined:
    Sep 9, 2016
    Posts:
    177
    See my answer here.
     
    joelsinbarba likes this.
  13. DrMox

    DrMox

    Joined:
    Dec 30, 2013
    Posts:
    5
    Hey just in case anyone has the same issue that David Foster had with every clip getting the last reference:

    You have to generate a new exposedName for it like so:
    Code (CSharp):
    1. exposedRef.exposedName = UnityEditor.GUID.Generate().ToString()