Getting objectData before ProcessFrame is called

Hi, I’m making a custom playable where I need the reference to the referenced asset in the CustomTrackAsset. I don’t know if it’s possible because the ProcessFrame in the PlayableBehavior script gets called last, and I need that reference for the OnBehaviourPlay method which gets called before ProcessFrame.

Notice in the behaviour script OnBehaviourPlay, there is where I need the “GameObject” reference.

Clip:

public class CustomPlayableAsset : PlayableAsset
{     
    public bool toLoad;

    public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
    {
        var playable = ScriptPlayable<CustomPlayableBehavior>.Create(graph);

        var scenePlayableBehavior = playable.GetBehaviour();
        scenePlayableBehavior.toLoad = toLoad;
        return playable;
    }
}

Behavior:

[System.Serializable]
public class CustomPlayableBehavior : PlayableBehaviour
{
    [Tooltip("true = load, false = unload")]
    public bool toLoad;
    GameObject gameObject;

    //like the Update
    public override void ProcessFrame(Playable playable, FrameData info, object playerData)
    {
        gameObject =  playerData as GameObject;
    }
   
    public override void OnBehaviourPlay(Playable playable, FrameData info)
    {
        base.OnBehaviourPlay(playable, info);
        if (gameObject != null)
        {
            //THIS DOESNT EXECUTE BECAUSE ITS NULL
        }
    }
}

Track:

[TrackColor(0, 0, 0)]
[TrackClipType(typeof(CustomPlayableAsset))]
[TrackBindingType(typeof(GameObject))]
public class CustomPlayableTrack : TrackAsset
{
    public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount)
    {
        return ScriptPlayable<CustomPlayableBehavior>.Create(graph, inputCount);
    }
    public override void GatherProperties(PlayableDirector director, IPropertyCollector driver)
    {
        base.GatherProperties(director, driver);
#if UNITY_EDITOR
        var comp = director.GetGenericBinding(this);
        if (comp == null)
            return;
        var so = new UnityEditor.SerializedObject(comp);
        var iter = so.GetIterator();
        while (iter.NextVisible(true))
        {
            if (iter.hasVisibleChildren)
                continue;
            driver.AddFromName(iter.propertyPath);
        }
#endif
        base.GatherProperties(director, driver);
    }
}

In the CreateTrackMixer, the GameObject (go) contains the playableDirector. You can get the binding for the track, and pass it to the custom clip, then in the CreatePlayable method of the clip pass it to the custom playable.

1 Like

Thank you it worked.

I took your previous post as an example.

I am also hunting this down… I got the first couple of steps… “In the CreateTrackMixer, the GameObject (go) contains the playableDirector. You can get the binding for the track, and pass it to the custom clip” but I am stuck here…

“then CreatePlayable method of the clip pass it to the custom playable” example?
and how then do I get this reference in the actual call to public virtual void OnBehaviourPlay(Playable playable, FrameData info)

Thanks

Using the example above, here is how to go about it. The gameObject will then be available to all methods in the CustomPlayableBehaviour, except OnPlayableCreate().

Note that the gameObject field in CustomPlayableBehaviour needs to public

public class CustomPlayableTrack : TrackAsset
{
    public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount)
    {
       var binding = go.GetComponent<PlayableDirector>().GetGenericBinding(this) as GameObject;

        foreach (var c in GetClips())
            ((CustomPlayableAsset)(c.asset)).gameObject = binding;

        return ScriptPlayable<CustomPlayableBehavior>.Create(graph, inputCount);
    }
...
}

public class CustomPlayableAsset : PlayableAsset
{  
    public bool toLoad;
    public GameObject gameObject {get;set;}   // should be public and not serializable.

    public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
    {
        var playable = ScriptPlayable<CustomPlayableBehavior>.Create(graph);

        var scenePlayableBehavior = playable.GetBehaviour();
        scenePlayableBehavior.toLoad = toLoad;
        scenePlayableBehavior.gameObject = gameObject;
        return playable;
    }
}
7 Likes