Good day, everyone!
Okay, so here’s the deal: I’ve been fiddling with some code over the past few days, and I’m currently not seeing a solution that I’m pretty sure is right in front of me. It’s kind of like having a massive tool bag, but not being sure which is the right tool for the job.
I’m working on a rotation system that will allow the user to input a target rotation rate in degrees per second, according to each of the local axis of rotation. Effectively, pitch yaw and roll on a spaceship. The physics system then applies appropriate local angular torque to said object.
I’ve managed to get the code written that will apply forces appropriately based on the values put in, but I’m running into a problem where, between fixed update steps, the values will momentarily exceed the target. The result is a nasty back-and-forth between applying opposing forces on the model when it approaches the target values, as it never arrives at the exact value specified. I’m hoping to find a way to force the vector to be the target value once the numbers are close enough, but I’m out of ideas on where/how to do so atm. Which is ridiculous, since mathf.clamp seems to work fine just about everywhere else.
Any assistance would be appreciated. Here is the current hacked together code. It works with a test cube that has a rigidbody mass of 300 and 0 angular drag.
using UnityEngine;
using System.Collections;
public class ShipRotation : MonoBehaviour {
public float rotationSpeed = 300f;
public float maxTurn = 6f; //maximum turn in degrees per second before structural damage or crew injury is possible
public float maxPitch = 6f; //maximum pitch in degrees per second before structural damage or crew injury is possible
public float maxRoll = 6f; //maximum roll in degrees per second before structural damage or crew injury is possible
public Vector3 setRotation = Vector3.zero; //set rotation in degrees per second
public Vector3 naturalTargetRotation = Vector3.zero; //current rotation in radians
public Vector3 currentRotation = Vector3.zero; //current rotation in degrees per second
public Vector3 forceToApply = Vector3.zero; //calculated vector information for relative torque
void FixedUpdate () {
Vector3 tmpVector = transform.InverseTransformDirection(GetComponent<Rigidbody>().angularVelocity);
currentRotation = new Vector3 (tmpVector.x * Mathf.Rad2Deg, tmpVector.y * Mathf.Rad2Deg,tmpVector.z * Mathf.Rad2Deg);
naturalTargetRotation = new Vector3 (setRotation.x * Mathf.Deg2Rad, setRotation.y * Mathf.Deg2Rad, setRotation.z * Mathf.Deg2Rad);
ProcessTurn ();
}
void ProcessTurn()
{
CapTurns ();
if (currentRotation.x == setRotation.x){
forceToApply.x = 0f;
} else if (currentRotation.x > setRotation.x) {
forceToApply.x = -rotationSpeed * Time.fixedDeltaTime;
} else if (currentRotation.x < setRotation.x) {
forceToApply.x = rotationSpeed * Time.fixedDeltaTime;
}
if (currentRotation.y == setRotation.y){
forceToApply.y = 0f;
} else if (currentRotation.y > setRotation.y) {
forceToApply.y = -rotationSpeed*Time.fixedDeltaTime;
}
else if (currentRotation.y < setRotation.y) {
forceToApply.y = rotationSpeed*Time.fixedDeltaTime;
}
if (currentRotation.z == setRotation.z){
forceToApply.z = 0f;
} else if (currentRotation.z > setRotation.z) {
forceToApply.z = -rotationSpeed*Time.fixedDeltaTime;
}
else if (currentRotation.z < setRotation.z) {
forceToApply.z = rotationSpeed*Time.fixedDeltaTime;
}
GetComponent<Rigidbody> ().AddRelativeTorque (forceToApply);
}
void CapTurns()
{
if (currentRotation.magnitude <= 0.08f) {
//currentRotation = setRotation;
}
Debug.Log (currentRotation.x - setRotation.x);
}
}