Good morning,
I am observing a scenario where a 3D rigidbody cube behaves inconsistently between turning left & turning right. I am attempting to move the cube like a vehicle and stay compliant with the physics system (I’m using addforce/addtorque instead of adjusting some rigidbody values directly). Across several sessions, I have tweaked numerous values hoping to discover what causes this behavior. So far, I have had no luck isolating the issue.
I have ran low on ideas, but this behavior is really bothering me. I have circumvented the issue in the past by upping the torque value, but I was intending to improve finer control when this behavior reared its ugly head again. I wanted to post the question and see if the community had any experience or feedback regarding the issue.
I have attached a video displaying the behavior: rigidbodyTurning - YouTube
Additionally, here’s a code sample of the most relevant area. I believe I am applying the torque forces in the same manner both positively and negatively, but I could certainly have overlooked something.
forwardInput = Input.GetAxis("Vertical");
lateralInput = Input.GetAxis("Q/E");
pivotInput = Input.GetAxis("Horizontal");
if (Math.Abs(pivotInput) > 0f)
{
pivotCurrent = 0.16f * Math.Sign(pivotInput); ;
}
else if (Math.Abs(pivotInput) == 0f)
{
float subtractAmount = 1f;
if (Math.Abs(pivotCurrent) <= 1f)
{
subtractAmount = Math.Abs(pivotCurrent);
}
pivotCurrent = (Math.Abs(pivotCurrent) - subtractAmount) * Math.Sign(pivotCurrent);
}
float maxPivot = 60f;
pivotCurrent = Mathf.Clamp(pivotCurrent, -maxPivot, maxPivot);
pivotProduct = Vector3.up * pivotCurrent;
if (BoxCaseGroundCheck())
{
myRigidbody.AddRelativeTorque(pivotProduct, ForceMode.Impulse);
myRigidbody.AddRelativeForce(Vector3.forward * forwardInput * forwardMultiplier, ForceMode.Force);
myRigidbody.AddRelativeForce(Vector3.right * lateralInput * lateralMultiplier, ForceMode.Force);
if (myRigidbody.velocity.sqrMagnitude > squareMaxVelocity)
{
RegulateVelocity();
}
}
Thanks for your time and attention regarding this behavior. Editted: Cleaned up some wording for clarity.
After investigating this issue further, it appears to be related to the friction component of the Player’s physic material. Setting dynamic friction/static friction to 0.0 seems to remove irregularities.
However, I have established a workable solution that seems to minimize the magnitude of the issue.
// Ang Vel of .4-.5 feels good for turning
// with Vel Change forcemode
// Forcemode.VelocityChange directly adjusts the angular velocity. Give or take some
// However, physic material Friction also seems to impact this. Add an additional offset for this
// Left and right turning is not precisely the same, but it's withing spitting distance.
// seems to be something related to friction physics-- setting to zero will ignore it
// Will be investigating "friction 2" functionality I discovered
forwardInput = Input.GetAxis("Vertical");
steeringInput = Input.GetAxis("Horizontal");
float deltaTargetAngularVelocity = 0f;
float localVelocityZ = transform.InverseTransformVector(myRigidbody.velocity).z;
float baseTarget = .75f;
// Checking it against zero didn't seem to function. checking it against a small value (.025 arbitrarily)
// seems to achieve the behavior
if (Math.Abs(localVelocityZ) >= 0.025f)
{
deltaTargetAngularVelocity = Steering2(baseTarget);
}
else
{
deltaTargetAngularVelocity = Steering2(baseTarget * 2.25f);
}
pivotProduct = Vector3.up * deltaTargetAngularVelocity;
if (BoxCaseGroundCheck())
{
myRigidbody.AddRelativeTorque(pivotProduct, ForceMode.VelocityChange);
myRigidbody.AddRelativeForce(Vector3.forward * forwardInput * forwardMultiplier, ForceMode.Force);
RegulateVelocity();
RegulateLateralVelocity();
}
float Steering2(float targetValue)
{
/*
* For some reason, I'm still seeing a variance on left/right turns. It seems to be something
* concerning friction values. Removing friction removes the variances.
* Until I can isolate it further, I've customized the steering function to degrade negative/
* left turn by 15%-- this seems to get the values in range at the setting angVel goal of .75
*/
Debug.Log(targetValue);
float deltaTargetAngularVelocity = 0f;
if (steeringInput != 0f)
{
float frictionValue = GetComponent<BoxCollider>().material.dynamicFriction;
float localAngularVelocityY = transform.InverseTransformVector(myRigidbody.angularVelocity).y;
float targetedAngularVelocity = targetValue * Math.Sign(steeringInput);
deltaTargetAngularVelocity = targetedAngularVelocity - localAngularVelocityY;
if(steeringInput > 0)
{
deltaTargetAngularVelocity += frictionValue * Math.Sign(steeringInput);
}else if (steeringInput < 0 )
{
deltaTargetAngularVelocity += frictionValue * Math.Sign(steeringInput) * .85f;
}
}
return deltaTargetAngularVelocity;
}
Beyond refactoring the code, the major changes were:
- Changed Forcemode to Velocity Change. This takes some of the guesswork out of a torque to angular velocity conversion. It’s not precisely there, but it’s close enough to work with.
- In the same vein, it seems like dynamic/static friction component impacts velocity change nearly 1 to 1. adding the friction value to addTorque’s force seems to do a respectable job.
- Within the Steering2() functon, I wrote out a bit of code to scale back Left-turning by about 15%. This puts it roughly in line with RIght-turning with my specific setup. Additionally, even ignoring the 15% offset, this bit of code seemed to perform respectably, and probably wouldn’t have noticed the differences between left and right turning were it not for tracking the value onscreen.
Ultimately, I am pleased with the solution, and wanted to share it here in case anyone else experiences this issue.
The root of the question still remains though:
Why is there a ~15% turning variance between a left turn and a right turn?
This issue may be closed.