Hello! I'm trying to clamp only my x rotation between -90 and 90 degrees using: private float xRotation = 0.0f; void Update() { xRotation = Mathf.Clamp(xRotation, -90, 90); transform.eulerAngles = new Vector3(xRotation, 0.0f, 0.0f); } However, the result of this is that my character can only rotate -1 to 1 on all axis. I don't understand why this is working like that. Iv'e been looking through all code samples and trying things for 2 hours now. Any help is very much appreciated
When you set the rotation to that value, it's going to completely overwrite your Y and Z values. So those two are effectively being "clamped" at 0. I don't see how you're ever changing the value of xRotation, but unless there's other code that affects that value, you're probably also setting that to 0. If you ever see values other than 0 in any of your rotation values, I strongly suspect the only reason is because whatever Update is rotating your thing, is happening after this code sets everything to 0... because this code definitely sets everything to 0. Trying to clamp rotation is not as simple as it sounds, mostly because Euler angles are terrible. (Yes, it's a long article, but read the whole thing - it's important.) It's not possible to simply (and reliably) clamp the Euler angles to specific values because any given rotation has multiple valid Euler angle equivalents. In order to properly help you determine how to accomplish your clamping goal, I'd need to see more context. If, for example, you're trying to clamp a viewing angle that's being moved by mouse movement, you'll want to use the mouse movement to modify something like your xRotation variable, and then do the same for a yRotation variable - those movements would have to affect those variables directly, you cannot get those variables from the transform's rotation value.
Oh, ok. I'll check out your article. I'm just moving the character by the character controller. I'm trying to accomplish smooth moving by the arrow keys with rotation that follows the player's direction along with a force always pushing the player forward. Also I want the player to slow down when they turn. In short, I'm trying to accomplish a moving system as in Mario Odyssey's Bullet Bill () That is all pretty much accomplished in my script public class PlayerController : MonoBehaviour { public float speed = 6.0F; public float baseSpeed; public float rotateSpeed = 3.0F; private Vector3 moveDirection = Vector3.zero; private float rotatingStart; private float rotatingUpdate; void Update() { //make speed stay above 50 if (speed < 50) { speed = 50; } //check if player is rotating along y and adjust speed rotatingStart = transform.rotation.y; if (rotatingStart != rotatingUpdate) { speed -= 5; rotatingUpdate = rotatingStart; } else { if (speed < baseSpeed) { speed++; } } //move player CharacterController controller = GetComponent<CharacterController>(); transform.Translate(Vector3.forward * speed * Time.deltaTime); moveDirection = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical" ), 0); moveDirection = transform.TransformDirection(moveDirection); controller.Move(moveDirection * speed * Time.deltaTime); //Rotate Player transform.Rotate(-Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"), 0); } } It's just that when the player rotates 'up' along the x axis, he will be able to flip a full circle and as a result, he will become wonky which is why I wish to restrict rotation on x. I hope I'm being clear ^^;
I want to guess that you mean limiting the camera and not the player? If you keep track of a variable, that you adjust based on input, you can clamp that 1 variable (it sounds like you only want one), and then apply them together.. Code (csharp): float rotationX = 0; float rotationY = 0; // you might also have some rotation speed variable void Update() { rotationX += Input.GetAxis("Vertical") * Time.deltaTime; rotationX = Mathf.Clamp(rotationX, minRotationX, maxRotationX); rotationY += Input.GetAxis("Horizontal" * Time.deltaTime; transform.rotation = Quaternion.Euler(rotationX, rotationY, 0); }
I'm trying to limit the player. I gave your script a try and my character's rotation bounces back to zero. I kinda just want to to stay based on the player's input between two values ^^;
Okay, the player.. um.. Did you add the min and max rotation & maybe some speed? Currently it's probably very slow.
Yes, I added a ton of speed. The way that's acting for me is that it always wants to be neutral. So whenever the player stops feeding it input, the values return to 0.
Code (CSharp): float rotationX = 0; float rotationY = 0; float minRotationX = -9; float maxRotationX = 9; void Update() { rotationX += Input.GetAxis("Vertical") * rotateSpeed * Time.deltaTime; rotationX = Mathf.Clamp(rotationX, minRotationX, maxRotationX); rotationY = transform.rotation.y; transform.rotation = Quaternion.Euler(rotationX, rotationY, 0);
hm.. So I copied exactly what you pasted here into a script, which I placed on a cube.. it's working perfectly for me. Perhaps paste your full Update, if maybe there is other stuff interfering?
I'm not sure...This is my entire script Code (CSharp): using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerController : MonoBehaviour { public float speed = 6.0F; public float baseSpeed; public float rotateSpeed = 3.0F; private Vector3 moveDirection = Vector3.zero; private float rotatingStart; private float rotatingUpdate; float rotationX = 0; float rotationY = 0; float minRotationX = -9; float maxRotationX = 9; void Update() { rotationX += Input.GetAxis("Vertical") * rotateSpeed * Time.deltaTime; rotationX = Mathf.Clamp(rotationX, minRotationX, maxRotationX); rotationY = transform.rotation.y; transform.rotation = Quaternion.Euler(rotationX, rotationY, 0); //make speed stay above 50 if (speed < 70) { speed = 70; } //check if player is rotating along y and adjust speed rotatingStart = transform.rotation.y; if (rotatingStart != rotatingUpdate) { speed -= 3; rotatingUpdate = rotatingStart; } else { if (speed < baseSpeed) { speed++; } } //move player CharacterController controller = GetComponent<CharacterController>(); transform.Translate(Vector3.forward * speed * Time.deltaTime); moveDirection = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical" ), 0); moveDirection = transform.TransformDirection(moveDirection); controller.Move(moveDirection * speed * Time.deltaTime); //Rotate Player transform.Rotate(-Input.GetAxis("Vertical")* rotateSpeed, Input.GetAxis("Horizontal") * rotateSpeed, 0); } }
Well, sure you still have your old rotate code at the bottom there Just change the rotationY in the snippet I wrote you to be what it was originally...(this): Code (csharp): rotationY += Input.GetAxis("Horizontal" * Time.deltaTime * rotateSpeed; // added speed then, comment out your rotate at the bottom & see if it works
Aww, I can't believe I forgot to do that Thank you so so much, it works great now! For anyone else reading this who may have my problem/or want my movement system, here's the complete code: Code (CSharp): using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerController : MonoBehaviour { public float speed = 6.0F; public float baseSpeed; public float rotateSpeed = 3.0F; private Vector3 moveDirection = Vector3.zero; private float rotatingStart; private float rotatingUpdate; float rotationX = 0; float rotationY = 0; float minRotationX = -45; float maxRotationX = 45; void Update() { rotationX += -Input.GetAxis("Vertical") * rotateSpeed * Time.deltaTime; rotationX = Mathf.Clamp(rotationX, minRotationX, maxRotationX); rotationY += Input.GetAxis("Horizontal") * Time.deltaTime * rotateSpeed; // added speed transform.rotation = Quaternion.Euler(rotationX, rotationY, 0); //make speed stay above 50 if (speed < 30) { speed = 30; } //check if player is rotating along y and adjust speed rotatingStart = transform.rotation.y; if (rotatingStart != rotatingUpdate) { speed -= 5; rotatingUpdate = rotatingStart; } else { if (speed < baseSpeed) { speed++; } } //move player CharacterController controller = GetComponent<CharacterController>(); transform.Translate(Vector3.forward * speed * Time.deltaTime); moveDirection = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical" ), 0); moveDirection = transform.TransformDirection(moveDirection); controller.Move(moveDirection * speed * Time.deltaTime); } }
Cool, I'm glad it's working for you. Just 1 small note for reference, in case you didn't already know. transform.rotation.y is not a euler angle representation. That is the 'y' component of a quaternion. I often see people confusing the two when getting/setting (did it too when I started). Enjoy your game