UltimateCharacterLocomotion.UpdateLocation = FixedUpdate + FinalIK Has Jitters at Low FPS

airoll

Member
Hello we are building a game for VR where the target FPS is 90 - as a result, we also are running our FixedUpdate at 90Hz as well. However, we have noticed that when our game is running at low FPS, the character starts to jitter and fire in the wrong direction. Here's a quick video of what we mean. The character is supposed to shoot at another character, but instead it shoots sideways.

Our character controller is using UpdateLocation.FixedUpdate, since that's required by several of the other packages we are using or planning to use. We are also using a FinalIKBridge that calls UpdateIK() on every Move() call (whether it's an update, fixed update, or late update).

We've been able to isolate the problem to the following. In KinematicObjectManager, we have the following code in FixedUpdate:

C#:
/// <summary>
        /// Moves the kinematic objects and characters.
        /// </summary>
        private void FixedUpdate()
        {
            // The kinematic object and cameras should be moved first so the characters receive the most recent changes.
            for (int i = 0; i < m_KinematicObjectCount; ++i) {
                if (m_KinematicObjects[i].IKinematicObject.UpdateLocation == UpdateLocation.Update) {
                    continue;
                }
                m_KinematicObjects[i].Move(true);
            }

            for (int i = 0; i < m_CharacterCount; ++i) {
                if (m_Characters[i].CharacterLocomotion.UpdateLocation == UpdateLocation.Update) {
                    continue;
                }
                if (!m_AutoSyncTransforms) {
                    Physics.SyncTransforms();
                }
                m_Characters[i].Move(false);
                if (m_Characters[i].CharacterIK != null && m_Characters[i].CharacterIK.enabled) {
                    m_Characters[i].CharacterIK.Move(true);
                }
                // If FixedUpdate is called multiple times before Update then the framerate is low.
                // Update the position immediately to prevent jittering.
                if (m_FixedUpdate) {
                    m_Characters[i].AssignFixedLocation(true);
                }
            }

            // Remember the time so SmoothMove can determine how much interpolation is necessary.
            m_FixedTime = Time.time;
            m_FixedUpdate = true;
        }

What happens when the character shoots sideways with low FPS, is that multiple FixedUpdates are called in succession before calling Update / LateUpdate. When that happens, the following code executes:

FixedUpdate 1
m_Character.Move(false)
m_Character.CharacterIK.Move(true) -> This calls FinalIK and fixes the position of the character's hand.
Unity internal animation update -> This resets the position of the character's hand so it shoots sideways.
FixedUpdate 2
m_Character.Move(false) -> This calls StartItemUse which fires the weapon, which is facing sideways.

Now, I'm wondering what's the best way to fix this issue with the least amount of unintended side effects.

Solution 1: Switch the order of m_Character.Move(...) and m_Character.CharacterIK.Move(...) so that the CharacterIK.Move() executes before the Character.Move().
I've tested this out, and it does fix the problem, but I'm wondering - will this cause unintended side effects?

Solution 2: Since there's already a flag for m_FixedUpdate that detects if FixedUpdate is called multiple times in a row, we could call CharacterIK.Move() if m_FixedUpdate is true before calling Character.Move().
Same question here - will this cause unintended side effects?

Solution 3: Other ideas on how to approach this problem?
This is something we must solve because during certain simulations our FPS will dip below the FixedUpdate rate.
 
If solution 1 fixes the issue then I will try that out as well with my FinalIK test scene. Since it's local to IK I don't see it causing any side effects.
 
Top