question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Wrong velocity calculation in RigidbodyAngularVelocity follow modifier

See original GitHub issue

Environment

  • Zinnia version: 1.25.0
  • Unity version: 2018.3+
  • 3rd party dependencies: None

Steps to reproduce

  1. Create an empty Unity project with Zinnia package added to it.
  2. Create a new empty scene.
  3. Setup objects: 3.1. Create a cube, name it “Follower Cube”. Scale to (0.1; 1; 10). 3.2. Create another cube, “Target Cube”. Scale to (0.1; 1; 10). 3.3. Create a new Material, paint it bright red and apply it to the “Follower”. It will help distinguish the objects visually. 3.4. Add non-kinematic Rigidbody to the “Follower Cube”. 3.5. Remove colliders form both cubes.
  4. Create script to rotate the “Target Cube” in FixedUpdate: 4.1. Create a new script, “RotateInFixedUpdate” (sample code below). Make it rotate a transform in FixedUpdate: 4.2. Add this script component to “Target Cube”.
  5. Setup Zinnia’s “ObjectFollower” script. 6.1. Put “Target Cube” to “Sources” list. 6.2. Put “Follower Cube” to “Targets” list. 6.3. Use “Rigidbody Angular Velocity” as Rotation Modifier. 6.4. Use any modifiers for position and scale (i.e. “Transform Position”, “Transform Scale”).
  6. In “Project Settings -> Time”, reduce physics timestep to 0.05 (20 FPS). This will make it easier to observe the effect.
  7. Run the scene.

Code for “RotateInFixedUpdate”:

using UnityEngine;

public class RotateInFixedUpdate : MonoBehaviour
{
    public float rotationSpeed = 60f;

    private void FixedUpdate()
    {
        var rotationDelta = new Vector3(0f,rotationSpeed,0f) * Time.deltaTime;
        transform.Rotate(rotationDelta);
    }
}

Expected behavior

“Follower” follows the “Target” rotation smoothly (with small offset due to FixedUpdate).

Current behavior

“Follower” jumps around the “Target” orientation each frame, but fails to align with it.

Possible cause

Current implementation of RigidbodyAngularVelocity follow modifier script calculates angle difference in degrees, clamps it and applies it directly to the velocity of follower Rigidbody (lines 48-61 of the original script):

Quaternion rotationDelta = source.transform.rotation * Quaternion.Inverse(offset != null ? offset.transform.rotation : target.transform.rotation);

rotationDelta.ToAngleAxis(out float angle, out Vector3 axis);
angle = angle.GetSignedDegree();

if (!angle.ApproxEquals(0))
{
    Vector3 angularTarget = angle * axis;
    Vector3 calculatedAngularVelocity = Vector3.MoveTowards(cachedTargetRigidbody.angularVelocity, angularTarget, MaxDistanceDelta);
    if (float.IsPositiveInfinity(AngularVelocityLimit) || calculatedAngularVelocity.sqrMagnitude < AngularVelocityLimit)
    {
        cachedTargetRigidbody.angularVelocity = calculatedAngularVelocity;
    }
}

There are 2 problems with this:

  1. “angle” is not converted to radians. Rigidbody.angularVelocity accepts radians, not degrees.
  2. “angle” is not divided by Time.deltaTime before being applied as a velocity.

Proposed solution

Convert angle to radians and divide it by deltaTime before applying it as angular velocity. This can be done by changing line 51 of current RigidbodyAngularVelocity script to:

angle = angle * Mathf.Deg2Rad / Time.deltaTime;

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:25 (22 by maintainers)

github_iconTop GitHub Comments

1reaction
thestonefoxcommented, Dec 10, 2020

Yup, this is the problem. I’ve added a GetSignedRadian method and turn the radians into signed radians and it fixes the problem with grabbing, and doesn’t introduce a problem with this original ticket

1reaction
thestonefoxcommented, Nov 26, 2020

the thing you’re talking about is already applied in the interactable prefab. It’s the MaxAngularVelocity by default is randomly set to 7 by unity, but it is forced to be infinity to prevent such issues.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Rigidbody velocity (and angular velocity) seem incorrect ...
When a rigidbody's movement is constrained/influenced by a joint, the rigidbody's linear and angular velocity properties no longer seem to ...
Read more >
Rigid Body Dynamics — physx 5.1.3 documentation
If a dynamic rigid actor is sleeping, the following state is guaranteed: The wake counter is zero. The linear and angular velocity is...
Read more >
Scripting API: Rigidbody.angularVelocity
The angular velocity vector of the rigidbody measured in radians per second. In most cases you should not modify it directly, as this...
Read more >
Rigid-bodies
Each rigid-body is given a linear damping coefficient (affecting its linear velocity) and an angular damping coefficient (affecting its angular velocity).
Read more >
Adaptive Tracking of Angular Velocity for a Planar Rigid ...
In this section, we analyze the stability of the adaptive feed- back linearization controller and prove global convergence of the angular velocity error...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found