1
\$\begingroup\$

I made a skinned 2D character and applied IK to each hand and leg.

In my game, player can aim up and down by moving fire joystick up and down. This is implemented by update "chest" bone's rotation in LateUpdate, because it renders after all animation stuffs.

Here'e the code I'm trying:

void Update() {
    // Handle move forward & backward
    ...

    m_FireMovement = new Vector2(m_FireJoystick.Vertical, m_FireJoystick.Horizontal);
    m_DeltaTime = Time.deltaTime;
}

void LateUpdate() {
    float verticalMovement = m_FireMovement.x;
    float horizontalMovement = m_FireMovement.y;

    // Which side facing? Depends on Fire Joystick.
    if (horizontalMovement < 0) {
        transform.rotation = Quaternion.Euler(0, 180, 0);
    }
    else {
        transform.rotation = Quaternion.Euler(0, 0, 0);
    }

    // Rotate chest bone depends on vertical input
    // TODO: Fix jittering issue
    float newRotation = verticalMovement * m_AimAmount * m_DeltaTime;
    m_ChestBone.Rotate(0, 0, newRotation);
}

It works, but there is noticeable jittering issue when aim up and down. Here's the video I recorded for demonstration: https://youtu.be/eYCY0NRG_AA

So I tried with using Coroutine, invoked from "Start" and keep looping and wait until WaitForEndOfFrame, and try rotate chest bone, but that makes it worse.

In 3D project, rotating bone in LateUpdate didn't make any problem. What am I missing?

Using Unity 2019.1.0f2 and 2D Animation Package@2.1.0, 2D IK@1.1.0.

\$\endgroup\$
  • 1
    \$\begingroup\$ At a glance, the multiplication by delta time would be my first suspect. This can fluctuate in magnitude depending on the framerate, making the distance you rotate the chest each frame inconsistent. \$\endgroup\$ – DMGregory Feb 4 at 17:56
3
\$\begingroup\$

You should not multiply by delta time here:

float newRotation = verticalMovement * m_AimAmount * m_DeltaTime;

Multiplication by delta time is useful when you're accumulating an incremental movement each frame, so the total movement builds at a consistent rate even if your frames are uneven durations.

But that's not what you're doing here.

Here, every frame the animation update resets the chest bone to its position & orientation in the animation data, erasing whatever you did to it last frame. So the correction you apply in LateUpdate isn't an incremental accumulation into a total state that persists from frame to frame. It's your one and only chance to snap that bone to where you want it.

If you multiply your correction by delta time, then on longer-than-normal frames you rotate further from the animated pose, and on short frames you rotate less. So the net result is that you vibrate back and forth in the vicinity of your average frame duration.

So, delete the delta time part here and adjust your aim amount variable to keep the overall rotation in your desired range.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thank you. Removing delta time works now! \$\endgroup\$ – modernator Feb 5 at 4:19
0
\$\begingroup\$

Smooth Quaternion Rotation - Unity Answers

Possible solution might be to rework the code to use Quaternion.RotateTowards();

Another thing to try would be a simple scalar multiplier on m_DeltaTime or m_AimAmount, sometimes multiplying it by a random number like 20.0f or 0.5f will help smooth newRotation by having less difference between frames.

If none of that helps, you could try reworking the m_FireMovement to also be a delta between frames (how has movement changed from last Update() ) or an offset from center / normal rotation

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ Thanks for posting a video! The stickman war vibes of the game look cool. Wish I could help more... \$\endgroup\$ – MrPickles7 Feb 4 at 21:15

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.