- Home /
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.
Thanks for the reply, I implemented the $$anonymous$$athf.Clamp on the rotation but its not having any effect, $$anonymous$$aybe i am putting it in the wrong place or i am using the wrong code.
transform.rotation.x = $$anonymous$$athf.Clamp(transform.rotation.x, -15, 25);
Ins$$anonymous$$d of using Quaternion.RotateTowards(), try Quaternion.Euler(). 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.
Answer by robertbu · Jan 13, 2014 at 11:36 AM
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 $$anonymous$$d 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.
Here is a simpler solution to the problem you ask here:
#pragma strict
var goTarget : GameObject;
var maxDegreesPerSecond : float = 30.0;
var maxDegrees = 25.0;
var $$anonymous$$Degrees = -15.0;
private var qTo : Quaternion;
function Start () {
qTo = goTarget.transform.localRotation;
}
function Update () {
var v3T = goTarget.transform.position - transform.position;
var v3Aim : Vector3;
var y = v3T.y;
v3T.y = 0.0;
var angle = $$anonymous$$athf.Atan2(y, v3T.magnitude) * $$anonymous$$athf.Rad2Deg;
angle = $$anonymous$$athf.Clamp(angle, $$anonymous$$Degrees, maxDegrees);
qTo = Quaternion.AngleAxis(-angle, Vector3.right);
transform.localRotation = Quaternion.RotateTowards(transform.localRotation, qTo, maxDegreesPerSecond * Time.deltaTime);
}
Here is a script that will handle a tank running over hills. Unlike the original scripts, this is an all-in-one script for both the turret and the gun. Currently it does limit the guns elevation, but not in the way you ask for here. Essentially when the target is out of range (above or below), it just doesn't change the elevation of the gun. It also defines the range a bit differently. You specify a maximum angle from the starting angle of the gun. So for example in your case where you want 25 up and 15 down, you would start with the gun elevated 5 degrees and specify 20 as the 'maxGunAngle'. This code could be rewritten to handle an explicit $$anonymous$$/max values as I've done in the scripts above, but I don't have time right now to make the changes. The technique to make the change would be similar to either of the two ways I've changed the scripts above.
#pragma strict
var target : Transform;
var gun : Transform;
var turretDegreesPerSecond : float = 45.0;
var gunDegreesPerSecond : float = 45.0;
var maxGunAngle = 45.0;
private var qTurret : Quaternion;
private var qGun : Quaternion;
private var qGunStart : Quaternion;
private var trans : Transform;
function Start() {
trans = transform;
qGunStart = gun.transform.localRotation;
}
function Update () {
var distanceToPlane = Vector3.Dot(trans.up, target.position - trans.position);
var planePoint = target.position - trans.up * distanceToPlane;
qTurret = Quaternion.LookRotation(planePoint - trans.position, transform.up);
transform.rotation = Quaternion.RotateTowards(transform.rotation, qTurret, turretDegreesPerSecond * Time.deltaTime);
var v3 = Vector3(0.0, distanceToPlane, (planePoint - transform.position).magnitude);
qGun = Quaternion.LookRotation(v3);
if (Quaternion.Angle(qGunStart, qGun) <= maxGunAngle)
gun.localRotation = Quaternion.RotateTowards(gun.localRotation, qGun, gunDegreesPerSecond * Time.deltaTime);
else
Debug.Log("Target beyond gun range");
}
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.
Answer by aldonaletto · Jan 13, 2014 at 10:29 AM
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, $$anonymous$$y 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.
Your answer
Follow this Question
Related Questions
0-360 Y degree from Vector3.Angle 1 Answer
90 degrees isnt? 2 Answers
Rotating A Character 180 Degress 1 Answer