Search Unity

  1. Unity 2020.1 has been released.
    Dismiss Notice
  2. We are looking for feedback on the experimental Unity Safe Mode which is aiming to help you resolve compilation errors faster during project startup.
    Dismiss Notice
  3. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Execute code after the animator update but before constraints are applied

Discussion in 'Animation Previews' started by customphase, Jul 17, 2020.

  1. customphase


    Aug 19, 2012
    For foot IK you're supposed to raycast to the current foot position and adjust the IK target/weight accordingly. Tried using LateUpdate, but constraints are applied before the LateUpdate. What to do?
  2. danUnity


    Apr 28, 2015
  3. customphase


    Aug 19, 2012
  4. danUnity


    Apr 28, 2015
    Each rig referenced in your rig builder is added as an AnimationPlayableOutput to your Animator. To change the order you can use the following extension method:

    The order is not guaranteed otherwise like explained in the following thread:

    "Yes, the PlayableGraph created for Animation Rigging has several outputs, this is no bug. The first output handles the SyncSceneToStream playable chain which synchronizes scene values to make them available to the Animation Rigging jobs. Afterwards, the other outputs handle the multiple Rigs set on your RigBuilder. The Animation Rigging outputs are set to use the previous input evaluation values so that they behave as a post process step to what was evaluated before (see

    We created a separate PlayableGraph in order for Animation Rigging to play nice with other animation systems. This way, we can use Animation Rigging with the Animator state machine or Timeline or your custom PlayableGraph.

    However, in 2019.2, we are missing a proper sorting order to better control when a PlayableGraph is evaluated in the Animator. While the Animator state machine always has priority on all other animation systems, we're not guaranteed that the Timeline PlayableGraph will be built before the AnimationRigging graph and thus in the right evaluation order.

    We're fixing that in 2019.3 by adding a sorting order to AnimationPlayableOutput (see

    In the meantime, to ensure your PlayableGraph are evaluated in the right order, make sure to also create them in the same order. By controlling when RigBuilder becomes enabled, you will also control when its PlayableGraph will be built, and thus change the evaluation order."
  5. tuinal


    Dec 14, 2012
    I had the same issue today, came up with a crude solution, by attaching the below script (tweaked from an example - 99% of the code is superfluous) as a child of an 'information' rig. It's constrained object needs to be a child of the root (I used an empty gameobject); the position of this constrained gameobject in Update is the animated position of the source object before IK in the previous frame - which is near enough for a decent raycast unless you're animating Road Runner. That's provided the rig is at the top of the stack in the rig builder, and whilst I've found it works I've not extensively tested it.

    This is an extremely convoluted way of getting at a simple Vector3, but in lieu of a sorely needed convenience method, or any real knowledge of the API, it's the only option I could find in the short time I had.

    It would help if the examples/docs had 1 good example of procedural target placement (foot IK being the best candidate). The vast majority of the documentation is on setting up and manipulating joints in the editor, rather than a worked-through use case. I get that it's meant to be a generic system and it's down to the developer/artist how the targets place themselves, but just one worked example that doesn't involve dragging an editor marker around would be extremely useful.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Animations.Rigging;
    5. using UnityEngine.Experimental.Animations;
    6. using Unity.Burst;
    7. using Unity.Mathematics;
    8. using UnityEngine.Animations;
    10. [BurstCompile]
    11. public struct AnimationInfoBinderJob : IWeightedAnimationJob
    12. {
    13.     public ReadWriteTransformHandle constrained;
    14.     public ReadOnlyTransformHandle source;
    17.     public FloatProperty jobWeight { get; set; }
    19.     public void ProcessRootMotion(AnimationStream stream) { }
    21.     public void ProcessAnimation(AnimationStream stream)
    22.     {
    23.         float w = jobWeight.Get(stream);
    24.         if (w > 0f)
    25.         {
    26.             constrained.SetPosition(
    27.                 stream,
    28.                 source.GetPosition(stream))
    29.                 ;
    30.         }
    31.     }
    34. }
    36. [System.Serializable]
    37. public struct AnimationInfoBinderData : IAnimationJobData
    38. {
    39.     public Transform constrainedObject;
    40.     [SyncSceneToStream] public Transform sourceObject;
    42.     public bool IsValid()
    43.     {
    44.         return !(constrainedObject == null || sourceObject == null);
    45.     }
    47.     public void SetDefaultValues()
    48.     {
    49.         constrainedObject = null;
    50.         sourceObject = null;
    51.     }
    52. }
    54. public class AnimationInfoBinderBinder : AnimationJobBinder<AnimationInfoBinderJob, AnimationInfoBinderData>
    55. {
    56.     public override AnimationInfoBinderJob Create(Animator animator, ref AnimationInfoBinderData data, Component component)
    57.     {
    58.         return new AnimationInfoBinderJob()
    59.         {
    60.             constrained = ReadWriteTransformHandle.Bind(animator, data.constrainedObject),
    61.             source = ReadOnlyTransformHandle.Bind(animator, data.sourceObject)
    62.         };
    63.     }
    65.     public override void Destroy(AnimationInfoBinderJob job) { }
    66. }
    69. public class AnimationInfoBinder : RigConstraint<
    70.     AnimationInfoBinderJob,
    71.     AnimationInfoBinderData,
    72.     AnimationInfoBinderBinder
    73.     >
    74. {
    75. }
  6. customphase


    Aug 19, 2012
    Yeah, figured that as well after the fact. Ive tried making my own playable behaviour but i couldnt manage to make it execute after the animator updated, even with that order thing. I assume its somehow related to that syncSceneToStream thing. Also according to the profiler, animator processing and animation rigging processing happens in parallel, so there is no actual inbetween step as is, as far as i can tell.

    Tried that as well, didnt work well for me. Anyway, for my solution i ditched the animation rigging altogether, ported the IK part of it (since thats the only thing i need from it really) as a regular main-thread code, and just used that in late update. The whole job/multithreading thing imo is extremely limiting and not necessary in 90% of cases anyway, most games are GPU bound nowadays.
  7. danUnity


    Apr 28, 2015
    Yeah the animation rigging constraint are added to the animator so they are definitely processed at the same time when the animation graph is evaluated. The order thing would be the solution for that if it worked...

    If I look at the events execution list there:

    Maybe you could have use the FixedUpdate? Also I have tried changing the Update Mode of the Animator?

    Glad you figured out a solution though!