Update Bone Positions After Animation with "Animate Physics"

I want to change the bone positions in script after the animation runs. This works fine if I put this code in LateUpdate. But I need to run my animator with “Animate Physics” so as far as I understand the animation is running in the FixedUpdate cycle. Sine there is no LateFixedUpdate there is no place for this code to be.

What is the right way to do this?

Could you give us a little bit more information on what you are trying to achieve?
How are you going to move this bone? with a physic force or simply set a new position?

Are you trying to implement a ragdoll to animation blending?

Are you trying to implement a ragdoll to animation blending?

Yes this.

I am running 2 skeletons and blending them. One with animation and one with a Ragdoll. I am blending them but at some point I will probably want to mask off bones to have them be controlled by animation or ragdoll.

I don’t understand why Unity is so stubborn about adding a LateFixedUpdate it is something people have been asking for years.

Take a look at this blog post, you will find a good example on how to achieve this,
going from mecanim to ragdoll is pretty easy but the inverse is not

All this can happen in LateUpdate as you are blending from your physic rig to your character animation.

1 Like

If you take this example and change the animator to “Animate Physics” it doesn’t work anymore.

This is because what he is doing in LateUpdate now needs to be done in the Fictional LateFixedUpdate. Which is really the point of the question.

We found a “solution” to this. We have this kludgey system in-place to deliver a LateFixedUpdate, using some bizarre use of a yeild statement to force unity to give us an opportunity to do something after the animator. We had this in place already because we needed a LateFixedUpdate for other things. It sucks that Unity can’t just provide this and we have to resort to things like this. It leaves me in fear that this side effect behavior will stop working at some point.

well that sucks, effectively it seem there is no way right now to fix this issue and honestly the current solution to blend from physic to animation is way to complex.

I will bring this to the animation team meeting and we will find a better solution.
As for the LateFixedUpdate I will talk with the scripting team to get their thought about this one.

1 Like

Thank you so much.

I’m also having the same problem since we have to use AnimatePhysics mode (it’s a hard requirement for our game).

The way I have tried to rig it, is to have a “PostFixedUpdate” function that is called before every FixedUpdate and Update – only if a FixedUpdate has occurred (evident by using timestamps). I still have to keep some timestamps because everything called inside PostFixedUpdate cannot rely on Time.deltaTime anymore (we don’t know if we have multiple updates in a row, or fixed updates in a row, etc).

In short, it will be really nice to have a callback after animation is done, so we can apply things like procedural rotations and full body IK

Hello, i’ve faced the same problem(but not for ragdolls) and tried following to deal:

  1. add StateMachineBehaviour to your states where you’re need PostFixedUpdate
  2. add your code to OnStateUpdate section
  3. profit(?!)(perhaps?)
    Actually it doesn’t solved my problem, but as i see in “Timeline” section of profiler it doing update exactly after “animations” update(when you’re in PhysicsUpdate mode) - so may be it can be ok for you.

Well yes the OnStateUpdate will be called after the Animation Update but the the animation system has not yet written all the animated values to unity so you can’t override the values in this callback.

But we are currently changing the animation system to behave more correctly with physic. Rather than overriding animation values in a LateFixedUpdate we want to add a new blending phase after the physic update.

Nice to hear, any suggestions on release time?

I can tell you that it won’t be in 5.6, maybe the next release after if everything goes well

Hi guys, well its good to find this :slight_smile:

because Im having this problem since forever, accidentally discover that it was because I was using Animate Physics mode, on update mode works fine but again I need the Animate Physics mode to my characters, and the get the same strange behaviour as @DDNA

@Mecanim-Dev any new hints on this? same issue on all unity versions :slight_smile:

The feature is currently in developpement, so it going forward but I have no idea when it will be available yet.

2 Likes

Is this coming with the new Timeline system, or is it still in the planning phases?

I am working on something that needs to be tied closely to physics (but not rely on it entirely) and I’d really prefer to know how performant this will be in Unity if I have to roll my own solution with manually setting transforms.

Here’s what I’ve gotta implement in Unity, and I’ve got to have bone-level physics control to do it:

http://www.gdcvault.com/play/1020583/Animation-Bootcamp-An-Indie-Approach

Any thoughts on a good performant approach to spring physics and secondary motions being combined with the custom blending curve interpolation necessary to achieve what’s in that video inside of Unity, @Mecanim-Dev ?

After 3 long years of beating me I found a solution!!!
OMG I’m so HAPPY!!

Just a simple line of Code and no more jittering

On Late Update
just call the Animator.Update(0f);
this will update all the bones positions and rotations using the animation is playing
after that you can make the modifications you need.

Here’s a simple example script on how to use it:
You just need to set the Animator to animate physics:

using UnityEngine;
    public class ModifyBoneInFixedUpdate : MonoBehaviour
    {
        public bool animatePhysics;
        public Animator anim; //Reference of the animator
        public Transform bone;      //Bone to modify                            
        public Vector3 offset = new Vector3(0,90,0); //offset to apply to the bone
        [Range(0,1)]
        public float Weight = 1;

        void LateUpdate()
        {
            if (animatePhysics)
            anim.Update(0);

            bone.rotation = Quaternion.Lerp(bone.rotation, bone.rotation * Quaternion.Euler(offset), Weight);
        }
    }

Thank you and good night! :sunglasses::stuck_out_tongue:

4737836–449120–ModifyBoneInFixedUpdate.cs (592 Bytes)

2 Likes

That code was causing some really weird behavior, the entire animator seemed a little fast. I don’t imagine it’s great for performance either.

My problem was that I wanted to apply an IK offset to animation default, but wasn’t able to without jitter. I was able to solve this problem by getting the ‘_lastBonePosition/Rotation’ as well the ‘_lastTransformPosition/Rotation’ in OnAnimatorIK. Then I would apply the offset to _lastBonePos/Rot while adding in the current transform position/rot difference.

Example:

        private void OnAnimatorIK(int layerIndex)
        {
            if (layerIndex != 0)
                return;

            _lastIKRootPosition = transform.position;
            _lastIKRootRotation = transform.rotation;

            if (_leftHandBone != null)
            {
                _lastLeftHandPosition = _leftHandBone.position;
                _lastLeftHandRotation = _leftHandBone.rotation;
            }
            if (_rightHandBone != null)
            {
                _lastRightHandPosition = _rightHandBone.position;
                _lastRightHandRotation = _rightHandBone.rotation;
            }
        }

UpdateToSpring(_leftSolver.solver, _lastLeftHandPosition, _lastLeftHandRotation, _leftPositionSpring, _leftRotationSpring);

        private void UpdateToSpring(IKSolverLimb solver, Vector3 startPos, Quaternion startRot, Spring positional, Spring rotational)
        {
            solver.target.position = (transform.position - _lastIKRootPosition) + startPos + _weaponDetailsHandler.transform.TransformDirection(positional.Value);
            solver.target.rotation = (transform.rotation * Quaternion.Inverse(_lastIKRootRotation)) * startRot * Quaternion.Inverse(Quaternion.Euler(rotational.Value));
            solver.Update();
        }
1 Like

Dude, your`are awesome. Thanks, it works!

2 Likes

What is its current status, has it been implemented?

1 Like