- Home /
Transform Z axis rotation from center of screen toward mouse cursor with Quaternion.LookRotation for a top down game.
I'm trying to get a plane to rotate on its Z axis only for a 2D top down shooter concept. I finished the Evac City tutorial and now am rewriting the code so that the games horizontal and vertical axes are X & Y (rather than X & Z like in the tutorial).
Here is my code that does not rotate the player sprite at all:
void Update () {
FindInput();
ProcessMovement();
if (thisIsPlayer == true) {
HandleCamera();
}
}
void FindPlayerInput () {
// find vector to move
inputMovement = new Vector3( Input.GetAxis("Horizontal"),Input.GetAxis("Vertical"),0 );
tempVector2 = new Vector3(Screen.width * 0.5f,Screen.height * 0.5f,0);
tempVector = Input.mousePosition;
tempVector.z = 0;
inputRotation = tempVector - tempVector2;
}
void ProcessMovement () {
rigidbody.AddForce( inputMovement.normalized * moveSpeed * Time.deltaTime );
transform.rotation = Quaternion.LookRotation(inputRotation);
transform.eulerAngles = new Vector3(0,0,transform.eulerAngles.z);
transform.position = new Vector3(transform.position.x,transform.position.y,0);
}
I've been stuck on this for about 8 hours of coming back to it and I'm losing my mind. The code in the tutorial (see below) works perfectly fine, all I am doing is leaving the Z axis perpendicular to the camera instead of swappying Z with Y like the tutorial shows.
Here is the tutorial code:
void Update () {
FindInput();
ProcessMovement();
if (thisIsPlayer == true) {
HandleCamera();
}
}
void FindPlayerInput () {
// find vector to move
inputMovement = new Vector3( Input.GetAxis("Horizontal"),0,Input.GetAxis("Vertical") );
// find vector to the mouse cursor / the position of the middle of the screen
tempVector2 = new Vector3(Screen.width * 0.5f,0,Screen.height * 0.5f);
// find the position of the mouse cursor on screen
tempVector = Input.mousePosition;
// input mouse position gives us 2D coordinates, moving Y coordinate to the Z coordinate in tempVector and setting the Y coordinate to 0 so the Vector will read the input along the X and Z axes (instead of X and Y)
tempVector.z = tempVector.y;
tempVector.y = 0;
// the direction to face/aim/shoot is from the middle of the screen to the mouse cursor
inputRotation = tempVector - tempVector2;
}
void ProcessMovement () {
rigidbody.AddForce (inputMovement.normalized * moveSpeed * Time.deltaTime);
transform.rotation = Quaternion.LookRotation(inputRotation);
transform.eulerAngles = new Vector3(0,transform.eulerAngles.y + 180,0);
transform.position = new Vector3(transform.position.x,0,transform.position.z);
}
Am I missing something about the world space in relation to the local space of the Player game object?
I guess this won't solve your problem, but I've spotted another error. It might just be a typo/failed copy or something.
You last line of code in Process$$anonymous$$ovement
transform.position = new Vector3(transform.position.x,transform);
you are missing inputs for your Vector3.
I'm not sure if what you have done works or not, but I would write all 3 inputs in any case.
Answer by EdgeGamer56k · Dec 10, 2012 at 08:21 AM
The line trans.eulerAngles = (0,trans.eulerAngles.y + 180,0); was only used in the tutorial. Because of the way the author decided to render the sprite onto the plane he needed the flip it on the y axis. I am choosing not to follow the tutorial exactly after completing it once already
I changed the ProcessMovement function to include the argument for the "up" position:
tempVector2 = new Vector3(Screen.width * 0.5f,Screen.height * 0.5f,0);
tempVector = Input.mousePosition;
tempVector.z = 0;
inputRotation = tempVector - tempVector2;
transform.rotation = Quaternion.LookRotation(inputRotation,Vector3.forward);
transform.eulerAngles = new Vector3(0,0,transform.eulerAngles.z);
Without the 'transform.eulerAngles' the plane finally rotates! However, the plane also rotates 90 degrees on its local x axis and stays fixed while it spins on its local y axis to follow the mouse. I am trying to get it to rotate on its z axis only.
When I use 'transform.eulerAngles' it only rotates on its z axis while snapping in 90 degree increments, and only rotating to 270, 0 and 90 degrees.
I'm still struggling to understand what is occurring with this code, but I'm determined to understand it, even if there is a better solution I still want to learn why this code is doing what it's doing.
The standard fix for an extra rotation is to make a empty parent, and add that extra rotation to the child.
And, again, the Unity docs really do say not to set rotation using only one eulerAngle, because it does exactly the weird things you're seeing.
Thanks for all the help, Owen! I understand not to set rotation using only one eulerAngle now. In fact, disabling the euler rotation did not seem to make a difference in the behavior but your suggestions worked after one alteration.
I had to re-export my plane mesh from Blender after rotating it in edit mode 90 degrees on the x axis so that in front view in Blender showed the z axis of the mesh was pointing up. Then the object rotated, but it was reversed. So i took your suggestions and these two lines are what did the trick:
tempVector.y = Screen.height - tempVector.y;
transform.rotation = Quaternion.LookRotation(inputRotation,Vector3.forward);
I had a feeling after so much struggling that this method was a terrible way of going about the rotation of my sprite. Ultimately, I am going to start over and make the top down transform use z as the vertical axis. I learned a lot from this and appreciate all your help. You've saved me a lot of headaches!
Answer by Owen-Reynolds · Dec 09, 2012 at 04:26 PM
The line in the original code about `trans.eulerAngles = (0,trans.eulerAngles.y + 180,0);` doesn't seem to do anything useful (it works fine w/o it.) And it breaks a rule from the docs. They say not to try to set just one eulerAngle. They all sort of interrelate.
It seems like you can make the `Quaternion.LookRotation(inputRotation)` work properly in the first place. The second optional input is the "up" position. For a top-down, you want up to be up, so they left it out. For a side view like you want, up should be towards you. Away is +Z, towards is -Z, so: `Q.LR(inpRot, -Vector3.forwards)`. That seemed to work for me.
If you have to do a 180, seems easier to flip the inputs, such as `tVec.y = SCreen.Height-tVec.y;`.
Your answer
Follow this Question
Related Questions
Rotating a 2D sprite to face a target on a single axis. 3 Answers
Lock Rotation of Object between 2 points, which is looking at the direction the mouse is pointing 0 Answers
Unity 2D: my LookRotation keeps rotating on the wrong axis 1 Answer
What causes this object to re-rotate itself after it hits it's destination? 1 Answer
LookRotation Vector3 is Zero, Yet Slerp Still Rotates? 2 Answers