Limit Object Angle

Hello,

I am not sure how to limit an objects degree of angle in my case 25 degrees up & 15 degrees down, Is there anyway for it to be implemented into this script?

var goTarget : GameObject;
var maxDegreesPerSecond : float = 60.0;
private var qTo : Quaternion;
 
function Start () {
    qTo = goTarget.transform.localRotation;
}
 
function Update () {
    var v3T = goTarget.transform.position - transform.position;
    var v3Aim : Vector3;
    v3Aim.x = 0.0;
    v3Aim.y = v3T.y;
    v3T.y = 0.0;
    v3Aim.z = v3T.magnitude;
    qTo = Quaternion.LookRotation(v3Aim, Vector3.up);
    transform.localRotation = Quaternion.RotateTowards(transform.localRotation, qTo, maxDegreesPerSecond * Time.deltaTime);
}

I have tried a few things but i just get errors popping up left right center, Any help would be greatly appreciated, Thanks.

See if this helps: [http://docs.unity3d.com/Documentation/ScriptReference/Mathf.Clamp.html][1] [1]: http://docs.unity3d.com/Documentation/ScriptReference/Mathf.Clamp.html

@getyour411 Thanks for the reply, I implemented the Mathf.Clamp on the rotation but its not having any effect, Maybe i am putting it in the wrong place or i am using the wrong code. transform.rotation.x = Mathf.Clamp(transform.rotation.x, -15, 25);

Any Ideas please?

Instead of using Quaternion.RotateTowards(), try [Quaternion.Euler()][1]. This will require some other modification of your script, but I had the same problem once upon a time and this is how I solved it. [1]: http://docs.unity3d.com/Documentation/ScriptReference/Quaternion.Euler.html

2 Answers

2

This code won’t work: you’re messing localRotation with global rotation, and the Vector3 math that calculates v3Aim doesn’t seem to produce something useful.

Limiting rotation angles is a complex job: you can’t rely on the Euler angles because at certain sectors they can switch to weird (although correct) combinations.

A possible solution is to decompose the desired direction into vertical and horizontal components, limit the vertical direction and join them into a limited direction vector - like this:

var maxAngle: float = 25;
var minAngle: float = -15;

function Update () {
  // get the normalized target direction:
  var dir = (goTarget.transform.position - transform.position).normalized;
  var maxSin = Mathf.Sin(maxAngle * Mathf.Deg2Rad); // get sine of max angle
  var minSin = Mathf.Sin(minAngle * Mathf.Deg2Rad); // get sine of min angle
  var sine = Mathf.Clamp(dir.y, minSin, maxSin); // get the clamped angle sine
  var cos = Mathf.Sqrt(1 - (sine * sine)); // calculate the cosine with Pythagoras
  // compound the new direction vector:
  dir = Vector3(dir.x, 0, dir.z).normalized * cos; // set the horizontal direction...
  dir.y = sine; // and set the vertical component
  qTo = Quaternion.LookRotation(dir, Vector3.up); // look at the new direction
  transform.rotation = Quaternion.RotateTowards(transform.rotation, qTo, maxDegreesPerSecond * Time.deltaTime);
}

Notice that this code takes advantage of the fact that in a normalized vector the Y component is numerically equal to the sine of the elevation angle: we can limit it to the desired range and create a new direction vector.

That beautiful script would be perfect if it was on a single turret, My script was intended for a barrel of a tank for vertical elevation, I have a separate script for the turret of the tank to only rotate on the Y axis, Sorry its my fault for not being specific enough, Your script would be perfect if it only it rotated on the X axis and not all axis, Thanks for Reply. Tank Hierarchy Tank Turret //rotates on y axis Gun // rotates on x axis The turret works as intended, Its the Gun that's bothering me.

Note when posting questions like this one and using code borrowed from another question, please make a reference to the original code. This 1) helps other such as @aldonaletto have the full context for an answer, 2) gives credit to the original author, and 3) makes it more likely that the original author will recognize the code and give you an answer. In this case, you borrowed the code from my answer here:

http://answers.unity3d.com/questions/388185/make-the-turret-automatically-rotate-to-look-at-wh.html

Note this code only works if you keep the turret parallel to the XZ plane. So if your tank is roaming over hills, you will need a different solution. As for limiting rotation, you can do it this way:

#pragma strict

var goTarget : GameObject;
var maxDegreesPerSecond : float = 30.0;

var maxDegrees = 25.0;
var minDegrees = -15.0;

private var qTo : Quaternion;
 
function Start () {
    qTo = goTarget.transform.localRotation;
}
 
function Update () {
    var v3T = goTarget.transform.position - transform.position;
    var v3Aim : Vector3;
    v3Aim.x = 0.0;
    v3Aim.y = v3T.y;
    v3T.y = 0.0;
    v3Aim.z = v3T.magnitude;
    
    var angle = Mathf.Atan2(v3Aim.y, v3Aim.z) * Mathf.Rad2Deg;
    
    if (angle > maxDegrees) {
    	v3Aim.y = Mathf.Tan(maxDegrees * Mathf.Deg2Rad) * v3Aim.z; 
    }
    
    if (angle < minDegrees) {
    	v3Aim.y = Mathf.Tan(minDegrees * Mathf.Deg2Rad) * v3Aim.z;
    }
    
    qTo = Quaternion.LookRotation(v3Aim);
    transform.localRotation = Quaternion.RotateTowards(transform.localRotation, qTo, maxDegreesPerSecond * Time.deltaTime);
}

The idea is that if the angle of the target is outside of your range, the ‘y’ value of the ‘v3Aim’ is recalculated to bring it up or down so that the angle is within range.

Sorry i will keep that in mind next time, Your modification works wonders but then i am back to facing the issue of the gun not looking at the goTarget when i am on any degree of slope, Thanks.

Aha,I suspected that the code was out of context! So you flatten the direction vector onto the plane YZ and calculate the elevation angle, clamp it to the range and calculate the clamped direction vector. I suppose that in this case localRotation will work fine with the value returned from LookRotation (provided that the turret is aligned to Y)

You sir are a legend, It surprisingly works better than i had intended, Thanks for the help guys much appreciated.