- Home /
[SOLVED]aligning rigidbody to be "level" with world's X and Z coords. How can I make sure it faces the same way (Y coord)?
So basically, my aircraft is flying. Once the player glides for a little bit, if their craft is not level, this code runs to "level" them back out, so their X and Z are closer to 0.
However, when this code runs, my Y ends up being much different, for example the aircraft will be going south but the correction, while doing ultimately what I need (leveling X / Z) , ends up with the plane facing east or a completely different direction.
I was considering, manually doing it first on the Z axis, and when that is done, manually doing it on the X axis. But reading around, and playing around with it, I'm concerned about gimbal lock affecting me such that, where my code might expect a value between 0-360, in reality (at least in the inspector) that number can keep going well beyond 360?
What is a good way to improve this? using System.Collections; using System.Collections.Generic; using UnityEngine;
public class PhysicsFlyer : MonoBehaviour {
public float AmbientSpeed = 100.0f;
public float RotationSpeed = 100.0f;
Rigidbody rb;
public bool needCorrecting;
public bool corrected = true;
[Header("Movement Input.")]
public float pitch;
public float yaw;
public float roll;
public float inputTimeout = 2f;
float itimer;
public bool havePushed;
public bool isLevel;
// Use this for initialization
void Start () {
rb = GetComponent<Rigidbody> ();
itimer = inputTimeout;
}
public float stability = 1f;
// public float speed = 2.0f;
// Update is called once per frame
void Update(){
if (Input.anyKey) {
havePushed = true;
corrected = false;
} else {
itimer -= .1f;
if (itimer <= 0f) {
itimer = inputTimeout;
havePushed = false;
}
}
if (Mathf.Abs (transform.rotation.eulerAngles.x) <= 15f) {
if (Mathf.Abs (transform.rotation.eulerAngles.z) <= 15f) {
print ("We are level");
isLevel = true;
} else {
isLevel = false;
}
} else {
isLevel = false;
}
if (!isLevel && !havePushed) {
if(!corrected)
needCorrecting = true;
} else {
needCorrecting = false;
}
}
void FixedUpdate () {
Quaternion AddRot = Quaternion.identity;
Vector3 torqueVector = Vector3.zero;
if (needCorrecting) {
Vector3 predictedUp = Quaternion.AngleAxis (
rb.angularVelocity.magnitude * Mathf.Rad2Deg * stability / 2f,
rb.angularVelocity
) * transform.up;
torqueVector = Vector3.Cross (predictedUp, Vector3.up);
torqueVector = new Vector3 (torqueVector.x, 0f, torqueVector.z);
print ("Correcting");
corrected = true;
}
float roll = 0;
float pitch = 0;
float yaw = 0;
roll = Input.GetAxis("Roll") * (Time.fixedDeltaTime * RotationSpeed);
pitch = Input.GetAxis("Vertical") * (Time.fixedDeltaTime * RotationSpeed);
yaw = Input.GetAxis("Horizontal") * (Time.fixedDeltaTime * RotationSpeed);
AddRot.eulerAngles += new Vector3(pitch, yaw, -roll);
if(corrected && needCorrecting)
AddRot.eulerAngles += torqueVector * 2f;
rb.rotation *= AddRot;
Vector3 AddPos = Vector3.forward;
AddPos = rb.rotation * AddPos;
rb.velocity = AddPos * (Time.fixedDeltaTime * AmbientSpeed);
}
}
Please,feel free to throw this script on a primitive shape like a cube with a rigidbody to see what I mean
Edit: Solution was to replace lines 95-105 with this code I found online from like 10 years ago and combining it with my last attempted solution:
levelPoint.transform.position = new Vector3(frontPoint.transform.position.x,rearPoint.transform.position.y,frontPoint.transform.position.z);
/*Where "frontPoint" is a gameobject at the front the craft, and "rearPoint" is at the rear, where typically we are pivoting around in my scenario....This way "levelPoint" is always globally in "front and level" to/of the craft.*/
var qTo = Quaternion.LookRotation(levelPoint.transform.position - transform.position);
qTo = Quaternion.Slerp(transform.rotation, qTo, 2f * Time.deltaTime);
rb.MoveRotation(qTo);
I don't understand the math, at least consciously, but it is doing exactly what I need it to. Hope this code helps someone but not too much because this is my pay dirt lol.