Search Unity

Writing a script to play an additive animation when a character is controlled by timeline.

Discussion in 'Timeline' started by QuickBirdiii, Nov 21, 2019.

  1. QuickBirdiii

    QuickBirdiii

    Joined:
    Nov 21, 2019
    Posts:
    1
    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?
     
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,728
  3. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    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.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Animations;
    5. using UnityEngine.Playables;
    6.  
    7. [ExecuteInEditMode]
    8. [RequireComponent(typeof(PlayableDirector))]
    9. public class PlayAdditive : MonoBehaviour
    10. {
    11.     private AnimationClipPlayable clipPlayable;
    12.  
    13.     public AnimationClip clip;
    14.     public AvatarMask mask;
    15.     public Animator who;
    16.  
    17.     private double startTime;
    18.  
    19.  
    20.     void Update()
    21.     {
    22.         if (clip == null || who == null)
    23.             return;
    24.  
    25.         if (!clipPlayable.IsValid())
    26.         {
    27.             var graph = GetComponent<PlayableDirector>().playableGraph;
    28.             if (graph.IsValid())
    29.             {
    30.                 startTime = graph.GetRootPlayable(0).GetTime(); // capture the current time
    31.             }
    32.  
    33.             for (int i = 0; i < graph.GetOutputCount(); i++)
    34.             {
    35.                 var output = (AnimationPlayableOutput) graph.GetOutputByType<AnimationPlayableOutput>(i);
    36.                 if (output.GetTarget() == who)
    37.                 {
    38.                     // get the root of the playable graph
    39.                     var outputPlayable = output.GetSourcePlayable().GetInput(output.GetSourceOutputPort());
    40.  
    41.                     // search the subgraph for the layer mixer
    42.                     while (outputPlayable.GetInputCount() > 0 && !outputPlayable.IsPlayableOfType<AnimationLayerMixerPlayable>())
    43.                         outputPlayable = outputPlayable.GetInput(0);
    44.  
    45.                     if (outputPlayable.IsValid())
    46.                     {
    47.                         var layerMixer = (AnimationLayerMixerPlayable) outputPlayable;
    48.                         clipPlayable = AnimationClipPlayable.Create(graph, clip);
    49.                         var inputIndex = layerMixer.AddInput(clipPlayable, 0, 1);
    50.  
    51.                         layerMixer.SetLayerAdditive((uint) inputIndex, true);
    52.                         layerMixer.SetLayerMaskFromAvatarMask((uint)inputIndex, mask);
    53.  
    54.                         startTime = GetComponent<PlayableDirector>().time;
    55.                     }
    56.                 }
    57.             }
    58.         }
    59.  
    60.         if (clipPlayable.IsValid())
    61.         {
    62.             clipPlayable.SetTime(GetComponent<PlayableDirector>().time - startTime);
    63.         }
    64.  
    65.     }
    66. }
     
  4. lk1

    lk1

    Joined:
    Feb 28, 2015
    Posts:
    3