Wrong velocity calculation in RigidbodyAngularVelocity follow modifier
See original GitHub issueEnvironment
- Zinnia version: 1.25.0
- Unity version: 2018.3+
- 3rd party dependencies: None
Steps to reproduce
- Create an empty Unity project with Zinnia package added to it.
- Create a new empty scene.
- 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.
- 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”.
- 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”).
- In “Project Settings -> Time”, reduce physics timestep to 0.05 (20 FPS). This will make it easier to observe the effect.
- 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:
- “angle” is not converted to radians. Rigidbody.angularVelocity accepts radians, not degrees.
- “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:
- Created 3 years ago
- Comments:25 (22 by maintainers)
Top 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 >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
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 ticketthe 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.