- Home /
How to freeze Z axis rotation in code?
Hi. I have problem with my camera script. It is aimed by mouse movement and is set to look at player. It works in vertical or horizontal way but when I move my mouse to corners my camera rotates at Z axis. How to freeze it in code? Also it is attached to look at player's right side but should stay behind him.
public class MouseAimCamera : MonoBehaviour {
public GameObject target;
public float rotateSpeed = 5;
void Start() {
transform.parent = target.transform;
transform.LookAt(target.transform);
}
void LateUpdate() {
float horizontal = Input.GetAxis("Mouse X") * rotateSpeed;
float vertical = Input.GetAxis("Mouse Y") * rotateSpeed;
target.transform.RotateAround(target.transform.position, Vector3.up, horizontal);
target.transform.RotateAround(target.transform.position, Vector3.left, vertical);
}
}
You just have to set it's z axis's euler angles to the desired value after rotating.
void LateUpdate() {
float horizontal = Input.GetAxis("$$anonymous$$ouse X") * rotateSpeed;
float vertical = Input.GetAxis("$$anonymous$$ouse Y") * rotateSpeed;
target.transform.RotateAround(target.transform.position, Vector3.up, horizontal);
target.transform.RotateAround(target.transform.position, Vector3.left, vertical);
Vector3 eulerAngles = target.transform.rotation.eulerAngles;
eulerAngles.z = 0;//or whatever rotation degrees you want
target.transform.rotation.eulerAngles = eulerAngles;
}
@Cherno it's impossible to do that, because compiler makes error when you try to modify rotation.eulerAngles, because it's temporary variable and can't be changed. Or I'm doing something wrong.
The problem is that it's not transform.rotation.eulerAngles.
It's just transform.eulerAngles.
First of all, the values you get from transform.rotation.eulerAngles
and transform.eulerAngles
are the same but assigning works slightly different.
transform.eulerAngles
can be assigned a Vector3.
Vector3 eulerAngles=new Vector3(0, 0, 0);
transform.eulerAngles=eulerAngles;
However you cannot directly assign a quaternion. Ins$$anonymous$$d you must convert the quaternion to a Vector3, i.e.
Quaternion rotation=new Quaternion(0, 0, 10, 10);
transform.eulerAngles=q.eulerAngles;
In contrast, transform.rotation
can be assigned a Quaternion.
Quaternion rotation=new Quaternion(0, 0, 10, 10);
transform.rotation=rotation;
However you cannot directly assign a Vector3. Ins$$anonymous$$d you must convert the Vector3 to a Quaternion, i.e.
Vector3 eulerAngles=new Vector3(0, 0, 0);
transform.rotation=Quaternion.Euler(eulerAngles);
Second of all reason the inspector displays different values than transform.eulerAngles is because the inspector displays the local rotation (relative to parent) while transform.rotation/transform.eulerAngles returns the global rotation (relative to world).
If you want to get the values displayed in the inspector use
transform.localRotation.eulerAngles
or the shorthand
transform.localEulerAngles
Answer by bolatharwatmee · Dec 01, 2020 at 12:33 PM
this worked for me
void FixedUpdate()
{
target.transform.Rotate(new Vector3(vertical, -horizontal, 0) * Time.deltaTime);
target.transform.eulerAngles = new Vector3(target.transform.eulerAngles.x,
target.transform.eulerAngles.y, 0);
}
Answer by PointyPigheadGames · Jul 06, 2017 at 02:47 PM
This is pretty easy to do. If your component has a rigidbody attached, use this code, and replace rb with the variable for your rigidbody:
rb.constraints = RigidbodyConstraints.FreezeRotationZ;
Won't work: rigidbody constraints only apply to forces generated by physics, not to movements/rotations applied to the transform.
Answer by aldonaletto · Jul 06, 2017 at 03:35 PM
Put LookAt inside Update, after the movement, this way the camera will adjust its orientation every frame (LookAt aligns to world up direction by default), :
target.transform.RotateAround(target.transform.position, Vector3.up, horizontal);
target.transform.RotateAround(target.transform.position, Vector3.left, vertical);
transform.LookAt(target.transform); // aim at the player
}
I like this. The website I got my info for my answer from stated that your options are do what I did. Or correct the role yourself. This corrects the role. So by all means go with this, but do yourself a favor and replace RotateAround with Rotate anyway. You don't want to use deprecated functions.
RotateAround isn't deprecated - at least I've seen no warning about that in the docs. RotateAround is hard to implement with other functions because it rotates de transform about a given axis and around a given point, showing always the same face to the center of rotation. But the magic could be done in this case with an auxiliary empty game object "sandwiched" between the camera and the target:
target
empty
camera
Rotating the empty object (with Rotate) will make the camera orbit the target just like RotateAround does in this code.
When I type RotateAround into VS it tells me to use Rotate.. idk. Anyway the OP is using RotateAround as Rotate anyway because the transform being rotated is used for the position of the rotate axis.
Which actually.. this is weird.. you are using the camera script to actually rotate the player and the camera only rotates around the player because of it being a child of the player, are you sure this is how you want to do this?
Answer by Jwizard93 · Jul 06, 2017 at 03:37 PM
First, don't use the deprecated RotateAround use Rotate instead. Next .. realize that I answered this exact same question twice yesterday.. It's clear you came from the same tut because you're code looks the same as theirs. But please try harder to search the site.
Rotation is not simple like translation because it is not commutative. Try to work it out in your head, rotating in two axes one at a time... you won't end up without rotation on the third axis. So you are probably getting unintentional role. You're case isn't too hard though. Try this. It eliminates what is called cross-contamination by defining the two separate rotations in different coordinates... Don't ask me how.. wish I knew.
target.transform.Rotate(Vector3.up, horizontal, Space.Self);
target.transform.Rotate(Vector3.right, vertical, Space.World);
Hope this helps! good luck. And hey, if you did come here with this code from a tutorial would you kindly bring this info over to it.. seems we are seeing a lot of this.
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
2D Raycast in any direction 1 Answer
What resolution should my game be? 2 Answers
Need to create a 3rd person camera controlled with a mouse 3 Answers