I’m working on a tank that rotates its barrel on the y axis to fire at a target, when the target is out of range I would like for the turret to reset the y rotation back to 0 over time.
I already have the system that detects when an enemy is in range or not, its just the rotation bit im having a problem with. Here is what I have to far:
function resetBarrel(){
print("resetting barrel");
if(transform.Rotate.y != 0){
//transform.Rotate.y ++;
print("barrel isnt at 0");
transform.Rotate(0, Time.deltaTime * 40, 0); //Time.deltaTime
}
else{
print("barrel at 0");
}
}
This function is called when the enemy is out of range. Whats happening is that the barrel begins to rotate when the enemy is out of range, but it just keeps on rotating. I think it has something to do with the “!=0” as maybe the transform.Rotate.y never hits zero exactly.
Maybe you could detect transform.Rotate.y < 0 or > 0 instead? And if it’s slightly off after having passed 0 (I’m thinking this would be a very small value), just set it to exactly 0 just after it has passed 0.
You should use a Quaternion.Slerp with a toRotation initialiazed with a Quaternion.LookRotation, that way you’re sure it won’t keep turning after 0. Then test if transform.rotation is closed to 0 (not equal, something like < 0.5) then snap it to 0 and stop calling resetBarrel.
You are right in that the rotation will never hit zero exactly, due to float values being used. You also have the issue of using transform.Rotate.y which should give you an error but does not for some reason (it should be transform.localEulerAngles.y). You also need to prevent the barrel from being rotated too far.
Here is a rewritted (untested) function for you (I also took the liberty of making it move in the best direction to get back to 0 the fastest).
function resetBarrel(){
print("resetting barrel");
var epsilon : float = 0.001f;
var currentAngle : float = transform.localEulerAngles.y;
if (currentAngle < 360 - epsilon && currentAngle > epsilon) {
print("barrel isnt at 0");
var angleDelta : float = Time.deltaTime * 40;
// positive if forward; negative if backward (rotation wise)
var rotMultiplier : int = (currentAngle > 180) ? 1 : -1;
var resultAngle : float =
Mathf.Clamp(currentAngle + rotMultiplier * angleDelta, 0, 360);
var rotation : Vector3 = transform.localEulerAngles;
rotation.y = resultAngle;
transform.localEulerAngles = rotation;
}
else {
print("barrel at 0");
}
}
Again, this is untested so there might be some lurking syntax/logic errors in here. The (currentAngle > 180) ? 1 : -1 part is so it rotates in the best direction (to get to 0 the fastest). If you don’t want that behavior, get rid of the variable (and remove the reference to it in the Mathf.Clamp line).
Ah jee thanks! Thats extremely nice of you, and it works perfectly. Many thanks!
Just one question though, the '(currentAngle > 180) ? 1 : -1;' could you explain to me what that actually means? I know its to get to zero the fastest, which works brilliantly. But what does it mean code wise? Thanks
Ah jee thanks! Thats extremely nice of you, and it works perfectly. Many thanks!
– oliver-jonesJust one question though, the '(currentAngle > 180) ? 1 : -1;' could you explain to me what that actually means? I know its to get to zero the fastest, which works brilliantly. But what does it mean code wise? Thanks
– oliver-jones