0
\$\begingroup\$

Some background to the question:

I am attempting to animate and control a large multi sprite 2D Boss character for a platforming game.

Up until this point I had been assigning individual animators for each of the limbs and using RigidBody2D to control the movement of each one respectively.

This worked fine except for one thing: synchronizing each animation state with the other controllers was a huge pain in the ass and error prone.


Hence my next step was creating one single Animation Controller using multiple layers to manage the animations together. This worked great, on the animation side of things. Catch was that now it had become completely impossible to alter the Transform of the the individual limbs (any child component below the animator)


 - Boss Character (main scripts and animator)
   -- BossHead (collider)
       -- SpriteHolder
   -- BossTorso (collider)
       -- SpriteHolder
   -- BossLeftHand (collider)
       -- SpriteHolder
   -- BossRightHand (collider)
       -- SpriteHolder

  • I have tried using transform.Translate instead of a RigidBody2D (same result)
  • I have tried checking apply root motion in the animator (same result)
  • I have doubly checked that no transform values were being modified during the animation (same result)

Unity version 2018.2.11

This use case does not seem to be all that unusual so there must be a correct workflow for this. Question is, what is the Unity correct way to achieve this?

EDIT: Code That updates the RigidBody2D

Void LateUpdate() {
    if (_path == null)
        return;

    if (_currentWaypoint >= _path.vectorPath.Count)
    {
        if (!_reachedEndOfPath)
        {
            _reachedEndOfPath = true;
            _rb.velocity = Vector2.zero;
            _callback?.Invoke();
        }
        return;
    }
    else
    {
        _reachedEndOfPath = false;
    }

    Vector2 direction = ((Vector2)_path.vectorPath[_currentWaypoint] - _rb.position).normalized;
    Vector2 force = direction * speed * Time.deltaTime;
    _rb.AddForce(force);

    float distance = Vector2.Distance(_rb.position, _path.vectorPath[_currentWaypoint]);
    if (distance <= _nextWaypointDistanceMargin)
        _currentWaypoint++;
}

Example of the effect I am attempting to create:

enter image description here

Main boss with two disembodied hands that can float around to chase the player.

\$\endgroup\$
  • \$\begingroup\$ "completely impossible to alter the Transform" can you show us the code you're using to do this? A common error here is to try to reposition objects in Update, before the animation update runs, instead of in LateUpdate, after the animation has done its work. \$\endgroup\$ – DMGregory Jun 17 '20 at 15:56
  • \$\begingroup\$ @DMGregory I added the code. What I meant by: "completely impossible to alter the Transform" Is that even when I go to Scene view and manually try to push the GO or alter it's Transform it will not change. \$\endgroup\$ – MSB Jun 17 '20 at 18:07
  • \$\begingroup\$ The approach you've shown here cannot work. You're trying to move the object with forces, which get evaluated in the physics step. But the animation update always happens after the physics steps for a frame, overriding wherever your forces brought your object to, replacing that position with the animated position. Can you show us an image or animation of how this character is supposed to behave, so we can suggest ways to achieve that behaviour? It's unclear from this sample how you want the animation and physical motion to combine. \$\endgroup\$ – DMGregory Jun 17 '20 at 18:26
  • \$\begingroup\$ @DMGregory I added a visual example of what I am attempting the create, the hands would float around the room chasing the player in an attempt to kill him. On a side note the animation does not alter the Transform of the hands in any way. \$\endgroup\$ – MSB Jun 17 '20 at 19:52
  • \$\begingroup\$ @DMGregory He is saying that the animator doesn't affect the Transform, but from the symptoms it does sound like there's a keyframe in there somewhere he missed. FWIW you can configure an Animator to update during the Physics step; see my answer. \$\endgroup\$ – Kevin Jun 19 '20 at 18:08
0
\$\begingroup\$

Animators and Rigidbodies do not work well together. If the Animator alters the transform.position of the different components, this will override any Rigidbody physics. You might see twitching from the Rigidbody "fighting with" the Animator.

If I'm understanding your situation correctly, there are two possible approaches:

  1. Throw out the Animator and animate everything with code. This can be tedious and the resulting code can be hard to follow in some cases, but it may be your best option if you want to combine physics with animation.

  2. Throw out force-based physics and only use Animators. If you still need the body parts to have Rigidbodies for the purposes of collision detection, set the Rigidbodies to be Kinematic and set the Update Mode of the Animator(s) to "Animate Physics"

\$\endgroup\$
  • \$\begingroup\$ Thanks for the answer just one question: Does it mean that Transform.Translate also affects physics in some way then? The reason I ask is that the animator does not change the transform values of either hand at all. \$\endgroup\$ – MSB Jun 17 '20 at 19:49
  • \$\begingroup\$ @MSB Transform.Translate moves the position of the object. If you have physics enabled, the physics also moves the position of the object. They can "fight", for example if you're trying to move an object up with a script while gravity is trying to move it down. If your code to translate objects or apply physics to them isn't working, that suggests that you have keyframes for position somewhere in the animation. \$\endgroup\$ – Kevin Jun 19 '20 at 18:07
  • \$\begingroup\$ @MSB Did you try changing the update mode of the Animator to "Animate Physics"? \$\endgroup\$ – Kevin Jun 19 '20 at 18:09
  • \$\begingroup\$ Yes this did not change anything. I Have been writing code to bypass the problem by switching out the entire prefab for another when playing specific animations but am still puzzled as to why it's not working in the first place. \$\endgroup\$ – MSB Jun 26 '20 at 12:15
  • \$\begingroup\$ @MSB It really sounds like you have a position keyframe in there somewhere, or some other animation setting that's overriding the physics. Unfortunately I can't think of anything else to suggest other than carefully going over the Animator and each of the animation clips to try to find a setting that would affect this. \$\endgroup\$ – Kevin Jun 26 '20 at 17:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.