Peculiar Bleed-through of Exposed References on different Timeline Tracks

I am experiencing some confusion regarding exposed references. I am assigning the track binding to a particular type of clip that will output at runtime to limb targets (my target class is named LimbController) for FinalK scripts. During editing, the clips need to know what LimbController they are affecting (only one target per track, so all the clips on a particular track will affect a single target, although there may be multiple tracks for different LimbControllers), so I have the Track set the exposed reference for each clip in the CreateTrackMixer method.

This seems to work just fine, with one exception–any clip on any track with an unassigned exposed reference will get a LimbController assigned to it if any LimbControlTrack has set a LimbControllers as it’s binding. This includes exposed references for other LimbControlClips but also includes completely unrelated and incompatible classes like CinemachineShots. (see image, below) .

Once an appropriate Exposed Reference has been assigned for a clip (or in the case of a different LimbControlTrack , for the entire track), the Exposed References seem to be stable and do not get over-written later. I seem to be unintentionally setting a LimbController reference as the default reference for any clip on any track that doesn’t have one already assigned to it via other means. The incorrect references can be corrected, and, once changed don’t revert, so this doesn’t seem (yet) to be a big deal, but I am concerned that there might be more to this than just pointless and temporary defaulting to an incorrect reference.

using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;
using System.Collections.Generic;

[TrackColor(1f, 0.384f, 0f)]
[TrackClipType(typeof(LimbControlClip))]
[TrackBindingType(typeof(LimbController))]
public class LimbControlTrack : TrackAsset
{
    public LimbController _mTrackBinding;

    public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount)
    {
        //check if track binding has been set 
        if (_mTrackBinding != null)
        {
            //iterator for all currently existing clips on this track
            IEnumerable<TimelineClip> clips = GetClips();
            PlayableDirector director = go.GetComponent<PlayableDirector>();
            //check each Timeline clip
            foreach (var item in clips)
            {
                // get LimbControlClip encapulated in TimelineClip container
                LimbControlClip limbControlClip = item.asset as LimbControlClip;
                // change ExposedName to name of trackbinding object to avoid
                // name collision when multiple LimbControlTracks in same Timeline
                limbControlClip.limbController.exposedName = _mTrackBinding.name;
                // assign exposedReference for clip
                director.SetReferenceValue(limbControlClip.limbController.exposedName, _mTrackBinding);
            }
        }
        return ScriptPlayable<LimbControlMixerBehaviour>.Create(graph, inputCount);
    }

    public override void GatherProperties(PlayableDirector director, IPropertyCollector driver)
    {
        LimbController trackBinding = director.GetGenericBinding(this) as LimbController;
        if (trackBinding == null)
            return;
        _mTrackBinding = trackBinding;
        base.GatherProperties(director, driver);
    }
}

You shouldn’t need to use an exposed reference per clip to get the track binding. The track binding is passed in the playerData parameter of PlayableBehaviour.ProcessFrame(). You just need to cast it to the binding type - in your case a LimbController.

This is purely needed during the editing process. When a particular LimbControlClip has been selected, it needs to be able to read data from the LimbController and store it in the clip’s behavour. During playback, you are correct, the exposed reference is not needed, but processframe doesn’t have access to the permanent LimbControlBehaviour, only a temporary clone.