Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Bug playable graph with 2 outputs not working

Discussion in 'Animation' started by JeremyJQ, Aug 13, 2021.

  1. JeremyJQ

    JeremyJQ

    Joined:
    Aug 13, 2021
    Posts:
    2
    Hi,
    We have this script to build a playable graph.

    There are two input animation clips: FullBodyClip with all bones in the skeleton animated; UpperBodyClip is from the same FBX file, but with an upper body mask, so only the bones in the upper body are animated.


    If BaseLayerUseFullBodyAnim is set to true, everything works fine.


    But if BaseLayerUseFullBodyAnim is set to false, and drag BlendingWeight between 0-1. The upper body animation is still correct, but lower body bone's rotations are way off (which is not same value as FullBodyClip, or avatar's default pose).

    The test is about two outputs. Output1 is connected to UpperBodyClip, with SortingOrder(10);

    OutPut2 is connected to m_mixer, with SortingOrder(10);

    m_mixer is just blending UpperBodyClip and FullBodyClip.

    Thanks a lot in advance.


    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Playables;
    3. using UnityEngine.Animations;
    4. using UnityEngine.Experimental.Animations;
    5.  
    6. [RequireComponent(typeof(Animator))]
    7. public class TwoOutputTest : MonoBehaviour
    8. {
    9.     public AnimationClip UpperBodyClip;
    10.     public AnimationClip FullBodyClip;
    11.     public AnimationStreamSource BaseLayerStreamSource = AnimationStreamSource.DefaultValues;
    12.     public AnimationStreamSource TopLayerStreamSource = AnimationStreamSource.DefaultValues;
    13.     public bool BaseLayerUseFullBodyAnim = true;
    14.     [Range(0f, 1f)]    public float BlendingWeight;
    15.  
    16.     private PlayableGraph m_playableGraph;
    17.     private AnimationMixerPlayable m_mixer;
    18.     //private AnimationLayerMixerPlayable m_layerMixer;
    19.  
    20.     void Start()
    21.     {
    22.         Start2outputTest();
    23.     }
    24.  
    25.     void OnDisable()
    26.     {
    27.         m_playableGraph.Destroy();
    28.     }
    29.  
    30.     [ContextMenu("start2outputTest")]
    31.     void Start2outputTest()
    32.     {
    33.         m_playableGraph = PlayableGraph.Create("2outputTest");
    34.         m_playableGraph.SetTimeUpdateMode(DirectorUpdateMode.GameTime);
    35.         Animator srcAnimator = this.GetComponent<Animator>();
    36.  
    37.         AnimationPlayableOutput o1 = AnimationPlayableOutput.Create(m_playableGraph, "layer0", srcAnimator);
    38.         var layer0ClipPlayable = AnimationClipPlayable.Create(m_playableGraph, BaseLayerUseFullBodyAnim? FullBodyClip: UpperBodyClip);
    39.         o1.SetSourcePlayable(layer0ClipPlayable);  
    40.         o1.SetSortingOrder(10);
    41.         o1.SetAnimationStreamSource(BaseLayerStreamSource);
    42.                
    43.         AnimationClipPlayable layer1ClipPlayable0 = AnimationClipPlayable.Create(m_playableGraph, UpperBodyClip);
    44.         AnimationClipPlayable layer1ClipPlayable1 = AnimationClipPlayable.Create(m_playableGraph, FullBodyClip);
    45.         m_mixer = AnimationMixerPlayable.Create(m_playableGraph, 2);
    46.         m_playableGraph.Connect(layer1ClipPlayable0, 0, m_mixer, 0);
    47.         m_playableGraph.Connect(layer1ClipPlayable1, 0, m_mixer, 1);
    48.  
    49.         AnimationPlayableOutput o2 = AnimationPlayableOutput.Create(m_playableGraph, "layer1", srcAnimator);
    50.         o2.SetSourcePlayable(m_mixer);      
    51.         o2.SetSortingOrder(20);
    52.         o2.SetAnimationStreamSource(TopLayerStreamSource);
    53.         m_playableGraph.Play();
    54.     }
    55.        
    56.     void Update()
    57.     {
    58.         m_mixer.SetInputWeight(0, 1f - BlendingWeight);
    59.         m_mixer.SetInputWeight(1, BlendingWeight);
    60.     }
    61. }
    62.  
     
  2. JeremyJQ

    JeremyJQ

    Joined:
    Aug 13, 2021
    Posts:
    2
    And we already know the workaround: instead of using two outputs, use just one output and connect it to a AnimationLayerMixerPlayable m_layerMixer , which has layer1 branch connected to UpperBodyClip; and layer2 connected to m_mixer. And it works correctly.

    But our project has some complicated playable graphs that must have multiple outputs, so we build this simplified test case to report the bug.


    Our understanding is SetSortingOrder() of two outputs will guarantee the top layer output override the base layer output’s animation. But when base layer output has FullBodyClip, everything works. If base layer output has UpperBodyClip, it somehow corrupted the animation data of top layer?
     
  3. DavidGeoffroy

    DavidGeoffroy

    Unity Technologies

    Joined:
    Sep 9, 2014
    Posts:
    542
    There are some issues with blending between outputs, which can be compounded by having clips with different sets of bones, Humanoid vs Genereic, as well as Animation masks. Some are fixable without breaking existing behaviour, some not.

    Behaviour may also vary quite a lot between Unity versions, as not all bugfixes are backported.

    Your best bet is to report this as a bug, so the Animation devs can debug with your assets and see exactly what the issue is.