Search Unity

Layered playables not working if placed under non-root node - what am I doing wrong?

Discussion in 'Animation' started by JaekSmith, Mar 3, 2018.

  1. JaekSmith

    JaekSmith

    Joined:
    Jul 30, 2014
    Posts:
    8
    I setup a script - see code at bottom - to allow separate animation control of each finger (with the non-thumb/index fingers bound together for now).

    When I place this at the root of the hierarchy, it works - the fingers control as I expect. When I place this under a node - such as an empty, only the thumb - e.g. the non-layered animations - work. The base animation - the thumb works either way, just the fingers - the layered animations - don't appear to have an effect.

    For now, I've quick-hacked a script to move the node under the target parent, which seems to work, but I expect I'm doing something wrong and this hack might fail at any time... :p

    [Notes]

    [Script]
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Playables;
    5. using UnityEngine.Animations;
    6.  
    7. public class PerFingerHandControl
    8.     : MonoBehaviour
    9. {
    10.     private const int thumbPositionClipIndex = 0;
    11.     public AnimationClip thumbPositionClip;
    12.     public Transform thumbTransform;
    13.     private AnimationClipPlayable thumbPositionPlayable;
    14.  
    15.     private const int indexPositionClipIndex = 1;
    16.     public AnimationClip indexPositionClip;
    17.     public Transform indexTransform;
    18.     private AnimationClipPlayable indexPositionPlayable;
    19.  
    20.     public AnimationClip middlePositionClip;
    21.     private const int middlePositionClipIndex = 2;
    22.     public Transform middleTransform;
    23.     private AnimationClipPlayable middlePositionPlayable;
    24.  
    25.     public AnimationClip ringPositionClip;
    26.     private const int ringPositionClipIndex = 3;
    27.     public Transform ringTransform;
    28.     private AnimationClipPlayable ringPositionPlayable;
    29.  
    30.     public AnimationClip pinkyPositionClip;
    31.     private const int pinkyPositionClipIndex = 4;
    32.     public Transform pinkyTransform;
    33.     private AnimationClipPlayable pinkyPositionPlayable;
    34.  
    35.     public PlayableGraph playableGraph;
    36.     public AnimationLayerMixerPlayable mixerPlayable;
    37.  
    38.     public string thumbButton2TouchId = "JoystickButton11";
    39.     public string thumbButton2PressId = "JoystickButton1";
    40.  
    41.     public string triggerTouchId = "JoystickAxis15";
    42.     public string triggerAxisId = "JoystickAxis10";
    43.  
    44.     public string gripAxisId = "JoystickAxis12";
    45.  
    46.     void Start()
    47.     {
    48.         playableGraph = PlayableGraph.Create();
    49.         playableGraph.SetTimeUpdateMode(DirectorUpdateMode.GameTime);
    50.  
    51.         AnimationPlayableOutput playableOutput = AnimationPlayableOutput.Create(playableGraph, "Animation", GetComponent<Animator>());
    52.  
    53.         mixerPlayable = AnimationLayerMixerPlayable.Create(playableGraph, 5);
    54.         playableOutput.SetSourcePlayable(mixerPlayable);
    55.  
    56.         thumbPositionPlayable = AddAnimationClipPayable(thumbPositionClip, thumbPositionClipIndex, null); // thumbTransform);
    57.         indexPositionPlayable = AddAnimationClipPayable(indexPositionClip, indexPositionClipIndex, indexTransform);
    58.         middlePositionPlayable = AddAnimationClipPayable(middlePositionClip, middlePositionClipIndex, middleTransform);
    59.         ringPositionPlayable = AddAnimationClipPayable(ringPositionClip, ringPositionClipIndex, ringTransform);
    60.         pinkyPositionPlayable = AddAnimationClipPayable(pinkyPositionClip, pinkyPositionClipIndex, pinkyTransform);
    61.  
    62.         playableGraph.Play();
    63.     }
    64.  
    65.     private AnimationClipPlayable AddAnimationClipPayable(AnimationClip animationClip, int clipIndex, Transform maskTransform)
    66.     {
    67.         AnimationClipPlayable playable = AnimationClipPlayable.Create(playableGraph, animationClip);
    68.         mixerPlayable.ConnectInput(clipIndex, playable, 0, 1f);
    69.  
    70.         if (maskTransform != null)
    71.         {
    72.             AvatarMask mask = new AvatarMask();
    73.             mask.AddTransformPath(maskTransform, true);
    74.             mixerPlayable.SetLayerMaskFromAvatarMask((uint) clipIndex, mask);
    75.         }
    76.  
    77.         playable.Pause<AnimationClipPlayable>();
    78.  
    79.         return playable;
    80.     }
    81.  
    82.     void OnDisable()
    83.     {
    84.         // Destroys all Playables and PlayableOutputs created by the graph.
    85.         playableGraph.Destroy();
    86.     }
    87.  
    88.     void Update()
    89.     {
    90.         float thumbWeight;
    91.         if (Input.GetButton(thumbButton2PressId))
    92.         {
    93.             thumbWeight = 1.0f;
    94.         }
    95.         else if (Input.GetButton(thumbButton2TouchId))
    96.         {
    97.             thumbWeight = 0.66f;
    98.         }
    99.         else
    100.         {
    101.             thumbWeight = 0.0f;
    102.         }
    103.         thumbPositionPlayable.SetTime<AnimationClipPlayable>(thumbWeight * thumbPositionClip.length);
    104.  
    105.         bool triggerTouched = Input.GetButton(triggerTouchId);
    106.  
    107.         float indexWeight;
    108.         float inputWeight = Input.GetAxis(triggerAxisId);
    109.         if (inputWeight != 0)
    110.         {
    111.             indexWeight = 0.1f + 0.9f * inputWeight;
    112.         }
    113.         else if (triggerTouched)
    114.         {
    115.             indexWeight = 0.1f;
    116.         }
    117.         else
    118.         {
    119.             indexWeight = 0.0f;
    120.         }
    121.         indexPositionPlayable.SetTime<AnimationClipPlayable>(indexWeight * indexPositionClip.length);
    122.  
    123.         float triFingerWeight;
    124.         float gripWeight = Input.GetAxis(gripAxisId);
    125.         if (gripWeight != 0)
    126.         {
    127.             triFingerWeight = 0.1f + 0.9f * gripWeight;
    128.         }
    129.         else if (triggerTouched)
    130.         {
    131.             triFingerWeight = 0.1f;
    132.         }
    133.         else
    134.         {
    135.             triFingerWeight = 0.0f;
    136.         }
    137.         middlePositionPlayable.SetTime<AnimationClipPlayable>(triFingerWeight * middlePositionClip.length);
    138.         ringPositionPlayable.SetTime<AnimationClipPlayable>(triFingerWeight * ringPositionClip.length);
    139.         pinkyPositionPlayable.SetTime<AnimationClipPlayable>(triFingerWeight * pinkyPositionClip.length);
    140.     }
    141. }
    Thanks!
     
  2. arshadameen

    arshadameen

    Joined:
    Mar 5, 2018
    Posts:
    8
    You need to recheck the code, especially line number 23, 45 and 121.
     
  3. JaekSmith

    JaekSmith

    Joined:
    Jul 30, 2014
    Posts:
    8
    Please explain your response? (It feels more like you are just making up something to get forum points...)
     
  4. JaekSmith

    JaekSmith

    Joined:
    Jul 30, 2014
    Posts:
    8
    Interestingly this issue / state / effect still exists after a year and in various new 2018 & 2019 versions ... still no clue what the issue is...
     
  5. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    My best guess is that it's being caused by the script execution order.

    Take a look at how the SimpleAnimationPlayable is set up. It's a PlayableBehaviour so it's part of the playable graph and does all its modifications to other playables in the PrepareFrame method instead of using a MonoBehaviour Update method.
     
  6. JaekSmith

    JaekSmith

    Joined:
    Jul 30, 2014
    Posts:
    8
    I tried converting my setup to do updates in a PlayableBehaviour - it didn't seem to work - whether my object was at the root or not. However, reviewing my code, this may be because of the way I'm setting the positions somewhat statically - setting the position in a paused animation... where-as the PlayableBehaviour is meant to update the animation state...

    I need to find some time to try to change it to update a running animation. If I recall, I did this originally because it was tweaking the positions I wanted - but this, most likely, was because I was not using a PlayableBehaviour - and, thus, how I arrived at my current solution. I haven't yet had the chance to try this yet, but wanted to post a response so that I could, at least thank you for the response/direction. =)

    Thanks!