How to get Angle float of specific axis.(Turret clamping related).

This is related to my previous question: How to clamp the rotation of this? - Unity Answers

Basically I am trying to clamp my barrel on a turret which slerps to a raycast hit by the camera. Everything I try to clamp it just messes it up. The closest I have come however is to get the direction angle of the turret to camera aim. So if its above a certain amount it won’t use lookrotation and slerp. However this is very clunky and I have to set it high makes the barrel turn on all axis.

So what I am trying to do now is get the degrees of the turret facing to the camera target on the x/z and y axis separately.

This is the basic code from the previous link.

What I need is to get two angles eg: angleB and angleA from the direction of the turret. In the code aimBAngle does such a thing but its on all axis. I need to get two separetely.

    aimTDir = transform.InverseTransformPoint(aimTarget.position);
     aimBAngle = Vector3.Angle(aimTDir, -transform.forward);
         if(aimBAngle < 50.0f){            
          Quaternion bRot = Quaternion.LookRotation(aimHitPoint - barrel.position);
          barrel.rotation = Quaternion.Slerp(barrel.rotation, bRot, Time.deltaTime * 5.0f);

Hope you understand… I also appreciate any other methods to solve this. Thanks. Its causing me great grief, so please help.

My game WIP:

Turret and barrel rotation gave me a huge headache as well. I finally got a satisfactory setup working, I don’t understand parts of my own code as I copied it from another user :slight_smile:

public Transform turretTransform; //drag the turret GO here
public Transform barrelTransform; //drag the barrel GO here
public float turretSpeed = 45f;
public float barrelSpeed = 45f;
private Quaternion qGun;
private Quaternion qGunStart;
private float maxGunAngle;
public float barrelRotMin = -10.0f;//play with this value to change how far the barrel can rotate downwards (actually an increase in rotation from 0 towards 10)
public float barrelRotMax = 35.0f;//play with this value to change how far the barrel can rotate downwards (actually a decrease in rotation from 0 towards 335 (=-35))
private Quaternion qTo;

//call in Start()
public void LoadTurretStats() {

		Quaternion qMin = new Quaternion();
		qMin.eulerAngles = new Vector3(barrelRotMin, 0, 0);
		Quaternion qMax = new Quaternion();
		qMax.eulerAngles = new Vector3(barrelRotMax, 0, 0);
		qGunStart = Quaternion.Slerp (qMin, qMax, -0.5f);//use a negative value or the min/max values will be reversed!
		maxGunAngle = Quaternion.Angle(qMin, qMax) / 2;
		gunStart = qGunStart.eulerAngles.x;

//Call CoRoutine from Update() while the vehicle/turret is active
//pass it the hit.point from your raycast
IEnumerator TurnTurret(Vector3 turretTargetPos ) {

		float distanceToPlane = Vector3.Dot(turretTransform.up, turretTargetPos - turretTransform.position);
		Vector3 planePoint = turretTargetPos - turretTransform.up * distanceToPlane;
		Quaternion qTurret = Quaternion.LookRotation(planePoint - turretTransform.position,turretTransform.up);
		turret.turretTransform.rotation = Quaternion.RotateTowards(turretTransform.rotation, qTurret, turretSpeed * Time.deltaTime);

		Vector3 v3 = new Vector3(0f, distanceToPlane, (planePoint - turretTransform.position).magnitude);
		turret.qGun = Quaternion.LookRotation(v3);

		barrelTransform.localRotation = Quaternion.RotateTowards(barrelTransform.localRotation, turret.qGun, barrelSpeed * Time.deltaTime);
		ClampRotation(barrelTransform, -maxGunAngle,  maxGunAngle,qGunStart.eulerAngles.x);

		yield return null;

//Used as a sub-function of te TurnTurret CoRoutine
void ClampRotation(Transform tr, float minAngle, float maxAngle, float clampAroundAngle) 	{
		//clampAroundAngle is the angle you want the clamp to originate from
		//For example a value of 90, with a min=-45 and max=45, will let the angle go 45 degrees away from 90
		//Adjust to make 0 be right side up
		clampAroundAngle += 180;
		//Get the angle of the z axis and rotate it up side down
		float x = tr.rotation.eulerAngles.x - clampAroundAngle;
		x = WrapAngle(x);
		//Move range to [-180, 180]
		x -= 180;
		//Clamp to desired range
		x = Mathf.Clamp(x, minAngle, maxAngle);
		//Move range back to [0, 360]
		x += 180;
		//Set the angle back to the transform and rotate it back to right side up
		tr.rotation = Quaternion.Euler(x + clampAroundAngle, tr.rotation.eulerAngles.y, tr.rotation.eulerAngles.z);

Solved it.

So the main part is angleB1 and angleB2. They calculate the x and z direction of the barrel and then only allows the slerp to target if within this range. aimB is a 3rd angle check directly from turrets forward direction to the target to stop the barrel snapping back since the aim target is coming from my camera and the other two angles calculate the rear facing the same as the forward.

		float aimB = Vector3.Angle(aimTDir, -transform.forward);

		aimBAngle1 = Mathf.Asin(Vector3.Cross(aimTDir.normalized, -transform.forward).x) * Mathf.Rad2Deg;
		aimBAngle2 = Mathf.Asin(Vector3.Cross(aimTDir.normalized, -transform.forward).z) * Mathf.Rad2Deg;

		if(aimB <= 45.0f){
		if(aimBAngle1 <= 45.0f && aimBAngle1 >= -20.0f && aimBAngle2 <= 10.0f && aimBAngle2 >= -10.0f){
			Quaternion bRot = Quaternion.LookRotation(aimPoint - barrel.position);
			barrel.rotation = Quaternion.Slerp(barrel.rotation, bRot, Time.deltaTime * 5.0f);