- Home /
How to clamp rotation in degrees in relation to another GameObject
So I am building a tank game in unity. As you know in tanks your turrets vertical movement is minimal and I have it clamped between 5 degrees down and 10 degrees up. This works fine on flat surface. My script takes my turrets current global rotation but I would like it to clamp the rotation in relation to my tanks main body. If I am in a hill the turret still wants to face up 10 degrees at max and the barrel goes trough my tanks body and the whole scene goes nuts. I will provide some pictures about the problem.
In the first picture everything is fine and I can look down 5- and up 10 degrees.
In the second picture you can see the problem. I can not look any higher than this because the turret is in its highest position (10 degrees) but not in relation to the tank. All help is appreciated! I will also post the looking script here.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class KameranLiikkuminen : MonoBehaviour
{
[SerializeField] private string mouseXInputName, mouseYInputName;
[SerializeField] private float mouseSensitivity;
[SerializeField] private Transform playerBody;
private float xAxisClamp;
private void Awake()
{
LockCursor();
xAxisClamp = 0.0f;
}
private void LockCursor()
{
Cursor.lockState = CursorLockMode.Locked;
}
private void Update()
{
CameraRotation();
}
private void CameraRotation()
{
float mouseX = Input.GetAxis(mouseXInputName) * mouseSensitivity * Time.deltaTime;
float mouseY = Input.GetAxis(mouseYInputName) * mouseSensitivity * Time.deltaTime;
xAxisClamp -= mouseY;
//Kameran kääntymis rajoitus vertikaalisesti
if(xAxisClamp > 5.0f)
{
xAxisClamp = 5.0f;
mouseY = 0.0f;
ClampXaxisRotationToValue(5.0f);
}
else if (xAxisClamp < -10.0f)
{
xAxisClamp = -10.0f;
mouseY = 0.0f;
ClampXaxisRotationToValue(-10.0f);
}
transform.Rotate(Vector3.right * -mouseY);
transform.Rotate(Vector3.up * mouseX);
ClampZaxisRotationToValue(0.0f);
}
private void ClampXaxisRotationToValue(float value)
{
Vector3 eulerRotation = transform.eulerAngles;
eulerRotation.x = value;
transform.eulerAngles = eulerRotation;
}
private void ClampZaxisRotationToValue(float value)
{
Vector3 eulerRotation = transform.eulerAngles;
eulerRotation.z = value;
transform.eulerAngles = eulerRotation;
}
}
Answer by unity_ek98vnTRplGj8Q · Dec 18, 2019 at 05:31 PM
If the turret is a child of the tank object (I assume it is) then you should clamp transform.localRotation.eulerAngles.x
to what you want, maybe something like this:
if(transform.localRotation.eulerAngles.x > 5){
transform.localRotation = Quaterion.Euler(new Vector3(5, transform.localRotation.eulerAngles.y, transform.localRotation.eulerAngles.z));
}
How would you implement that bit of code to my existing code? I am still a bit unfamiliar with C# so could you help me to do that. Thanks for the quick answer!
@Turz1 Try this out, I haven't tested it so let me know if it works or not. If not, we can tweak it to do exactly what you want. A couple things to note: I went ahead and changed around the structure of your code a bit if that's O$$anonymous$$. I also deviated a bit from the answer I gave to you earlier to more closely follow best practices for creating rotations (at least according to my understanding).
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class $$anonymous$$ameranLiikku$$anonymous$$en : $$anonymous$$onoBehaviour
{
[SerializeField] private string mouseXInputName, mouseYInputName;
[SerializeField] private float mouseSensitivity;
[SerializeField] private Transform playerBody;
private float xAxisClamp, yAxisClamp;
private void Awake()
{
LockCursor();
xAxisClamp = 0.0f;
}
private void LockCursor()
{
Cursor.lockState = CursorLock$$anonymous$$ode.Locked;
}
private void Update()
{
CameraRotation();
}
private void CameraRotation()
{
//Get mouse inputs
float mouseX = Input.GetAxis(mouseXInputName) * mouseSensitivity * Time.deltaTime;
float mouseY = Input.GetAxis(mouseYInputName) * mouseSensitivity * Time.deltaTime;
//Increment your x and y rotation values
xAxisClamp -= mouseY;
yAxisClamp += mouseX;
//Clamp x value
if(xAxisClamp > 5.0f) xAxisClamp = 5.0f;
else if (xAxisClamp < -10.0f) xAxisClamp = -10.0f;
//$$anonymous$$ake a rotation about the LOCAL x axis
Quaternion rotation = Quaternion.AngleAxis(xAxisClamp, transform.right);
//$$anonymous$$ake a rotation about the PARENT'S local y axis
rotation = rotation * Quaternion.AngleAxis(yAxisClamp, transform.parent.up);
//Set this rotation as the local rotation
transform.localRotation = rotation;
}
}
The reason that I am not using transform.Rotate() here is because this function is good for adding a delta rotation. That makes it harder to clamp, however, because you want to clamp your overall rotation, not your delta rotation. Ins$$anonymous$$d, I make an entirely new Quaternion every frame so that I can set the overall rotation which I can easily clamp.
Thanks a lot! This seems to work better but I think you have to also lock z axis because now the turret can turn around z axis and it get all twisted. Otherwise this seems to have fixed my problem. How can I completely lock the z axis in this script? I tried to mess around with it but I only got it to work with turrets local z axis again :( @unity_ek98vnTRplGj8Q
Your answer
Follow this Question
Related Questions
How to use mathf.clamp? 2 Answers
How to Clamp a Quaternion Camera Rotation? 0 Answers
Clamp rotation of object - Door 1 Answer
Clamped rotation of turret problem 0 Answers
How to clamp rotation between negative and positive value 2 Answers