Hi,
When a character’s animation and transformation are controlled by timeline, is it possible to write a script that when pressing a key, it plays an additive animation on that character?
Let say timeline is controlling character walking from one position to the other. During that time, if I press spacebar, the character would wave his hand while walking.
Is this possible?
That question is better asked on the Timeline forum: Unity Engine - Unity Discussions
Yes, it is possible, although it’s not possible to do on the animation track itself. But you can do it by manipulating the underlying playable graph once it is created.
Here’s a sample that should help you get started. It adds an additive layer to a timeline animation track via script that attaches to a playable director.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.Playables;
[ExecuteInEditMode]
[RequireComponent(typeof(PlayableDirector))]
public class PlayAdditive : MonoBehaviour
{
private AnimationClipPlayable clipPlayable;
public AnimationClip clip;
public AvatarMask mask;
public Animator who;
private double startTime;
void Update()
{
if (clip == null || who == null)
return;
if (!clipPlayable.IsValid())
{
var graph = GetComponent<PlayableDirector>().playableGraph;
if (graph.IsValid())
{
startTime = graph.GetRootPlayable(0).GetTime(); // capture the current time
}
for (int i = 0; i < graph.GetOutputCount(); i++)
{
var output = (AnimationPlayableOutput) graph.GetOutputByType<AnimationPlayableOutput>(i);
if (output.GetTarget() == who)
{
// get the root of the playable graph
var outputPlayable = output.GetSourcePlayable().GetInput(output.GetSourceOutputPort());
// search the subgraph for the layer mixer
while (outputPlayable.GetInputCount() > 0 && !outputPlayable.IsPlayableOfType<AnimationLayerMixerPlayable>())
outputPlayable = outputPlayable.GetInput(0);
if (outputPlayable.IsValid())
{
var layerMixer = (AnimationLayerMixerPlayable) outputPlayable;
clipPlayable = AnimationClipPlayable.Create(graph, clip);
var inputIndex = layerMixer.AddInput(clipPlayable, 0, 1);
layerMixer.SetLayerAdditive((uint) inputIndex, true);
layerMixer.SetLayerMaskFromAvatarMask((uint)inputIndex, mask);
startTime = GetComponent<PlayableDirector>().time;
}
}
}
}
if (clipPlayable.IsValid())
{
clipPlayable.SetTime(GetComponent<PlayableDirector>().time - startTime);
}
}
}