How to object rotate on a single axis towards another object? C#
I have an object A in a 3D world (ortho view). I want object A to rotate along the X axis to face object B. Object A must not change on the y and z axis.
Visual Aid: http://i.imgur.com/6VsBfGE.png - spaceship lies at a point with rotation 0, -90, 90. It must face the planet with the front of the ship, like this: http://i.imgur.com/cE94rlI.png
I've tried a whole range of things from other threads but can't get it working. Unity v5.5
Answer by TheDJBuntin · Jan 24, 2017 at 03:20 PM
So I knew I was complicating things far too much. So I took it down to the basics. This is my problem in its simplest form: http://i.imgur.com/ImcmpxQ.png
From the positions we can calculate the sides of the triangle with the code
float z = Vector3.Distance(objectB.transform.position, objectA.transform.position);
float x = objectB.transform.position.x - objectA.transform.position.x;
float y = objectB.transform.position.y - objectB.transform.position.y;
then we use the equation b = arccos((y2 + z2 - x2)/2yz) to calculate the angle:
float angle = Mathf.Acos((Mathf.Pow(y, 2.0f) + Mathf.Pow(z, 2.0f) - Mathf.Pow(x, 2.0f) / 2 * y * z));
BUT Mathf.Acos gives the number back in Radiants. So to convert to Degrees do:
angle *= Mathf.Rad2Deg;
However, if we were to put this into Rotate() right now, it would rotate the wrong way if ObjectB is on the right side of ObjectA, so we have to make the angle a negative if it is on the right hand side (ie if x position of ObjectB is larger than ObjectA's)
if (x > 0)
angle = -angle;
then finally, put this angle into the simple Rotate() function, rotating on the x axis
objectA.transform.Rotate(Vector3.forward, angle);
Here is the thing in its entirety for easy copy and pasting for anyone looking this up:
float z = Vector3.Distance(objectB.transform.position, objectA.transform.position);
float x = objectB.transform.position.x - objectA.transform.position.x;
float y = objectB.transform.position.y - objectB.transform.position.y;
float angle = Mathf.Acos((Mathf.Pow(y, 2.0f) + Mathf.Pow(z, 2.0f) - Mathf.Pow(x, 2.0f) / 2 * y * z));
angle *= Mathf.Rad2Deg;
if (x > 0)
angle = -angle;
objectA.transform.Rotate(Vector3.forward, angle);
Answer by BlueDragonHatch · Jan 24, 2017 at 06:12 AM
Wold a Quaternion.setfromtorotation work for you? So it would be kinda lige this:
public float speed;
void Update() {
float step = speed * Time.deltaTime;
transform.rotation = Quaternion.RotateTowards(A.rotation, Quaternion.setfromtorotation(A.Forwards, (B. Transform - A.Transform) ) , step);
}
Not sure ifølge A.forward is valid, but should work othervise, the B - A Thing is just to Construct Vector from A pointing towards B
Sorry for the spelling Errors, im om mobile and autocorrect is coding i sine :D
Here is the result: http://i.imgur.com/HbHH$$anonymous$$yo.png - The only difference is I set its position/rotation etc in an init function, so it should instantly be set to this new rotation, to combat this I just put 360 ins$$anonymous$$d of step.
Here is a cleaned up version of your code incase anyone comes across this, with $$anonymous$$or adjustments (ie forward for me is negative up and I set rotation to max as I want it to go instantly):
transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.FromToRotation(-transform.up, (Planet.transform.position - transform.position)), 360.0f);
With this, the ship is facing the planet which is good. But it has also moved the other axis's which isn't. The top of the ship should always face "up". The ship on the bottom of that screenshot is how it should look, the one on the left is incorrect.
Answer by _Keith · Feb 09, 2017 at 02:29 AM
transform.rotation = Quaternion.LookRotation(Vector3.forward, target.transform.position);