- Home /
Gimbal Lock like behavior using AddForceAtPosition in child objects
I have a GameObject which is acting as the parent GameObject to several other objects.
The parent is the only GameObject with a RigidBody attached to it.
Each child has the potential to add force to the parent RigidBody in order to move the overall object in some arbitrary direction.
The idea is that a force vector and magnitude are calculated in the child, then applied to the parent RigidBody to cause some sort of movement.
I'm using AddForceAtPosition in order to make it feel like the force is being applied at the child object, since the children don't have their own RigidBody component.
Below is the FixedUpdate from the child script (Some changes have been made to facilitate readability on this site).
public void FixedUpdate()
{
// Find velocity relative to main rigid body
this.localVelocity =
this.ParentRigidBody.GetPointVelocity(this.transform.position);
// Find vector perpendicular to local velocity,
// in the direction of local up.
this.forceVector = Vector3.Cross(
Vector3.Cross(this.localVelocity, this.transform.up),
this.localVelocity);
this.forceVector.Normalize();
// Find signed angle.
var theta1 = Vector3.Angle(this.localVelocity, this.transform.up);
var theta2 = Vector3.Angle(this.localVelocity, this.forceVector);
this.Angle = theta1 - theta2;
// Find speed squared
var speed = Vector3.Dot(this.localVelocity, this.transform.forward);
var sqrSpeed = Mathf.Pow(speed, 2);
// Calculate magnitude
// ForceTable.GetCoefficient takes a float 'angle' which it uses
// as the key in a key/value pair lookup.
// In general, positive angles will return positive
// coefficients, and negative angles will return negative coefficients.
// Coefficients are small [-1, 1], more or less.
var coefficient = ForceTable.GetCoefficient(this.Angle);
// this.InputOffset is, as it may sound, calculated based on user input.
// The value is pretty much always either -0.14f, 0f, or 0.14f
coefficient += this.InputOffset;
this.magnitude = 0.5f * sqrSpeed * this.Area * coefficient;
// apply force.
this.ParentRigidBody.AddForceAtPosition(
this.forceVector * this.magnitude,
this.transform.position);
}
The issue I'm having revolves (HA!) around rotation. In this case, I have two children objects, each placed on opposite sides of the parent's center of mass, with symmetry across the parent's local forward vector.
If I apply positive input to one child, and negative to the other, I would expect the overall object to rotate to the right or left.
For the most part, this works as expected.
The issue comes once the object hits 90 degrees (or -90 degrees) rotation, at which point the object stops rotating around the local forward vector, and begins rotating around the local left/right vector (now aligned with world 'up'). Normally I would scream 'gimbal lock!' and run about waving Quaternions, but since I'm not actually calculating and applying rotations, I feel like this is an unlikely culprit.
Your answer
Follow this Question
Related Questions
AddForceAtPosition Creating Torque When It Shouldn't 0 Answers
Unity 2019.3.0f6 - Trouble with physics, cubes turn left after some meters 1 Answer
Add force on objects from a specific location in space 2 Answers
How to limit the motion direction of a GameObject? 1 Answer
How to make foot don't cross the ball? 0 Answers