KybernetikGames / animancer

Documentation for the Animancer Unity Plugin.
66 stars 8 forks source link

How to add an IAnimationJob to the AnimationLayer #265

Closed raykingqd closed 1 year ago

raykingqd commented 1 year ago

How to add an IAnimationJob to the AnimationLayer. Because I need the job to collect the bone rotation of the first layer. Then you can use this data on other jobs or on lateupdate image

KybernetikGames commented 1 year ago

I've never really considered putting jobs anywhere other than the final output, but I can see why that might be useful.

Try something like this:

// Create your job playable.
var jobPlayable = AnimationScriptPlayable.Create(_Animancer.Playable.Graph, new MyJob(), 1);

// Get the layer and root layer mixer.
var layer = _Animancer.Layers[0];
var layerMixerPlayable = ((IPlayableWrapper)_Animancer.Playable).Playable;

// Disconnect the layer and connect the job in its place.
layerMixerPlayable.DisconnectInput(layer.Index);
layerMixerPlayable.ConnectInput(layer.Index, jobPlayable, 0);
layerMixerPlayable.SetInputWeight(0, layer.Weight);

// Connect the layer to the job instead.
jobPlayable.ConnectInput(0, layer.Playable, 0);
jobPlayable.SetInputWeight(0, 1);

That would break if the layer ever disconnects itself from the graph (such as if its Weight becomes 0). So it'd be fine if you're only doing it on layer 0, but otherwise you'd also need to set _Animancer.Playable.KeepChildrenConnected = true; beforehand.

raykingqd commented 1 year ago

image Thank you very much. Although there are a few problems, this is what I changed `

    var jobPlayable = AnimationScriptPlayable.Create(animancer.Playable.Graph, job, 1);

    // Get the layer and root layer mixer.
    var layer = animancer.Layers[0];
    Playable layerMixerPlayable = ((IPlayableWrapper)animancer.Playable).Playable;

    // Disconnect the layer and connect the job in its place.
    layerMixerPlayable.DisconnectInput(layer.Index);
    layerMixerPlayable.ConnectInput(layer.Index, jobPlayable, 0);
    layerMixerPlayable.SetInputWeight(0, layer.Weight);

    Playable layerPlayable = ((IPlayableWrapper)animancer.Layers[0]).Playable;
    // Connect the layer to the job instead.
    jobPlayable.ConnectInput(0, layerPlayable, 0);
    jobPlayable.SetInputWeight(0, 1);`
raykingqd commented 1 year ago

Finally, this structure is in line with my expectations! Thank you. image

KybernetikGames commented 1 year ago

layer.Playable was made public in Animancer v7.4 so you can avoid needing that cast if you update.

And I'll probably expose layerMixerPlayable in the next version (or see if I can come up with a better way to handle all this).

raykingqd commented 1 year ago

I only update to 6.0. Upgrading to 7.0 requires a regeneration of all