# Turret Slerp rotation and clamping

Firstly, following on from my turret rotation problem, which is now working wonderfully, I now need to smoothly rotate the turret between targets.

I tried doing it using:

``````transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(targetVector,hardpointPosition.transform.up), Time.deltaTime * turnspeed);

gun.transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(target.position-transform.position,hardpointPosition.transform.up), Time.deltaTime * turnspeed);
``````

While this did make the turret rotates as expected, the gun can now no longer rotate up or down, which is useless to me. How can I go about fixing this?

Secondly, I also need to prevent the gun from rotating too far downwards, to stop it from trying to aim through the bottom of the turret base. I only need to worry about the maximum downwards angle, as when the gun points directly up, the turret base rotates around to face the target, meaning the gun cannot rotate more than 90 degrees up. What’s the best way to go about sorting this out?

Here’s an excerpt from the Gun script I created for a tank game we worked on last year. In brief: it checks whether the aim point is left or right of a plane orthogonal to the local right of the rotating part of the turret (the turret base) and then checks whether the aim point is above or below a plane orthogonal to the local up of the elevating part of the turret (the gun). It could probably use some optimization, but you’re welcome to it…

``````    /// <summary>
/// The transform to rotate around the X axis (elevate) when aiming.
/// </summary>
public Transform elevator;

/// <summary>
/// The maximum elevation, in degress, below the zero point.
/// </summary>
public float minElevation;

/// <summary>
/// The maximum elevation, in degress, above the zero point.
/// </summary>
public float maxElevation;

/// <summary>
/// The transform to rotate around the Y axis (rotate) when aiming.
/// </summary>
public Transform rotator;

/// <summary>
/// The maximum rotation, in degress, to the left of the zero point.
/// </summary>
public float minRotation;

/// <summary>
/// The maximum rotation, in degress, to the right of the zero point.
/// </summary>
public float maxRotation;

/// <summary>
/// The accuracy of the weapon, in meters.
/// </summary>
public float accuracy;

/// <summary>
/// The speed at which the weapon may be turned.
/// </summary>
public float turnSpeed;

/// <summary>
/// Rotates and elevates the weapon torwards the target.
/// </summary>
/// <param name="target">The target to aim at.</param>
public virtual void Aim(Vector3 target)
{
// Get a plane through the rotation of the weapon
Plane rot = new Plane(rotator.right, rotator.position);
if (Mathf.Abs(rot.GetDistanceToPoint(target)) < accuracy)
return;

// And rotate towards target
if (rot.GetSide(target))
Rotate(1.0f); //right
else
Rotate(-1.0f); //left

// Get a plane through the elevation of the weapon
Plane elev = new Plane(elevator.up, elevator.position);
if (Mathf.Abs(elev.GetDistanceToPoint(target)) < accuracy)
return;

// And elevate towards target
if (elev.GetSide(target))
Elevate(1.0f); //up
else
Elevate(-1.0f); //down
}

/// <summary>
/// Pivots the weapon up(+) and down(-).
/// </summary>
/// <param name="direction">The direction to pivot; up is positive, down is negative.</param>
public virtual void Elevate(float direction)
{
// Clamp the direction input between -1 and 1...
direction = Mathf.Clamp(-direction, -1.0f, 1.0f);

// Calculate the new angle...
float angle = elevator.localEulerAngles.x + direction * turnSpeed * Time.deltaTime;
if (angle > 180)
angle -= 360;

// Clamp the new angle between the given minimum and maximum...
angle = Mathf.Clamp(angle, -maxElevation, -minElevation);

// Update the transform...
elevator.localEulerAngles = new Vector3(angle, elevator.localEulerAngles.y, elevator.localEulerAngles.z);
}

/// <summary>
/// Pivots the weapon right(+) and left(-).
/// </summary>
/// <param name="direction">The direction to pivot; right is positive, left is negative.</param>
public virtual void Rotate(float direction)
{
// Clamp the direction input between -1 and 1...
direction = Mathf.Clamp(direction, -1.0f, 1.0f);

// Calculate the new angle...
float angle = rotator.localEulerAngles.y + direction * turnSpeed * Time.deltaTime;
if (angle > 180)
angle -= 360;

// Clamp the new angle between the given minimum and maximum...
if (Mathf.Abs(minRotation) + Mathf.Abs(maxRotation) > 0)
angle = Mathf.Clamp(angle, minRotation, maxRotation);

// Update the transform...
rotator.localEulerAngles = new Vector3(rotator.localEulerAngles.x, angle, rotator.localEulerAngles.z);
}
``````

I have a couple of untested solutions for you. Usually for something like this, I test the solution, but I can’t right now. First take a look at my gun script in this answer: