Search code examples
c#unity-game-enginerotationlimit

How to set 2 limits to the rotation of an object?


I need to make the object rotate in the z axis when holding D to go up and W to go down but limit the rotation in both directions, with the code provided below i managed to make the object rotate when pressed but it does´t stop rotating when hit any of the 2 limits set with my variables.

I am new in the world of coding, hopefully you can help me to solve and understand my problem. Thank you for your time in advance.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GyroDiscControls : MonoBehaviour{

public GameObject AltNeedleBright;
public float MaxAltNeedleRotation = -65f;
public float MinAltNeedleRotation = 135f ;
public void update (){

if (Input.GetAxisRaw("Vertical") > 0 & 
AltNeedleBright.transform.rotation.z > MaxAltNeedleRotation)
    {
        AltNeedleBright.transform.Rotate(0f, 0f, +15f * Time.deltaTime);
    }
if (Input.GetAxisRaw("Vertical") < 0 & 
AltNeedleBright.transform.rotation.z < MinAltNeedleRotation)
    {
        AltNeedleBright.transform.Rotate(0f, 0f, -15f * Time.deltaTime);
    }

}


Solution

  • First of all you are dealing with Quaternion. Quaternion has 4 components x, y, z and w and does not behave like you expect it here - never change or check a rotation.z value directly.

    The second mistake: transform.Rotate by default does the rotation in local Space .. so checking transform.rotation is wrong anywway .. if something it should be transform.localRotation.

    Then the value you actually wanted to check is the transform.localEulerAngles or eulerAngles.


    A simple alternative would be to store the already rotated value and clamp on that instead:

    // Your naming is very confusing ... Min should be the smaller value
    public float MaxAltNeedleRotation = 135f;
    public float MinAltNeedleRotation = -65f;
    
    private float alreadyRotated = 0;
    
    public void update ()
    { 
        var direction = 0;
    
        // use && here .. you don't want to do a bitwise & on bools
        if (Input.GetAxisRaw("Vertical") > 0 && alreadyRotated < MaxAltNeedleRotation)
        {
            direction = 1;
        }
        // use else if since anyway only one of the cases can be true
        else if (Input.GetAxisRaw("Vertical") < 0 && alreadyRotated > MinAltNeedleRotation)
        {
            direction = -1;
        }
    
        // use the rotation and riection
        // but clamp it so it can minimum be MinAltNeedleRotation - alreadyRotated
        // and maximum MaxAltNeedleRotation - alreadyRotated
        var rotation = Mathf.Clamp(direction * 15f * Time.deltaTime, MinAltNeedleRotation - alreadyRotated, MaxAltNeedleRotation - alreadyRotated);
    
        if(rotation != 0)
        {
            AltNeedleBright.transform.Rotate(Vector3.forward * rotation);
    
            // update the alreadyRotated value
            alreadyRotated += rotation;
        }
    }