Turret question

Hi everybody.

I am kinda new to programming, I’m actually an artist just trying to build an initial prototype for presentation, and I’m having a bit of trouble figuring out some operations that envolve quaternions.

I’m trying to get a turret to work in a way similar to a tank: The base of the turret rotates along the X axis while the cannon itself rotates along the Y axis as they point at the mouse cursor from a 3rd person follow cam.

I read a few threads regarding turrets and raycast and mixed up a few lines of code to achieve the effect and it does work, but only if the turret is mounted facing up on the world coordinates… and i need them to work with turrets that can be mounted with their local up facing any direction.

The vehicle:
vehicle
----turretmount1(located atop the vehicle (up = 0)
----turretmount2(located to the right of the vehicle (up = 270)
----turretmount3(located atop the vehicle (up = 90)
----turretmount4(located atop the vehicle (up = 180)

the turrets instantiate parented one to each turret mount and are built like:
mountpoint <----- Script is attached here
----base (for X rotation)
--------cannon (for Y rotation)

The code i pasted together, mainly form Charles Hinshaw:

var targetrange:float = 1000.0;
var _parent : Transform;
var xConstraint = 20;
var yConstraint = 20;
var damping = 20;

function Update () {

	var ray : Ray = Camera.main.ScreenPointToRay(Vector3(Input.mousePosition.x,Input.mousePosition.y,0));
	var rayHit : RaycastHit;
		
	Debug.DrawRay(ray.origin, ray.direction * targetrange, Color.yellow);

	var rot = Quaternion.LookRotation(ray.GetPoint(targetrange) - transform.position, transform.up);
	var rotationX = rot.eulerAngles.y;
	var rotationY = rot.eulerAngles.x;
	rotationX = ClampAngle(rotationX, -xConstraint, xConstraint);
	rotationY = ClampAngle(rotationY, -yConstraint, yConstraint);
	rotationY = -rotationY;
	var xQuaternion = Quaternion.AngleAxis(rotationX, Vector3.up);
	var yQuaternion = Quaternion.AngleAxis(rotationY, Vector3.left);
	transform.localRotation = Quaternion.Slerp(transform.localRotation, xQuaternion * yQuaternion, Time.deltaTime * damping);

	print(rot.eulerAngles);
	
	
	
}

function ClampAngle(angle, min, max){

	if (min < 0) min += 360;
		if (angle > 180){
			return Mathf.Clamp(angle, min, 360);		
		} else {
			return Mathf.Clamp(angle, 0, max);
	}

}

I tried fixing it on my own, but my own limitations right now are taking me far too long for this. Perhaps a simple pointer willl shed some light on the subject for me.

Thanks in advance guys.

Hi again.

After many hours of burning my eyes in front of the screen I eventually came up with this… it’s ALMOST perfect but still has one hiccup.

The GOOD:
Each Turret mounts on it’s own mountpoint and inherits it’s facings
AND
all of them point correctly at where they should(raycast from mouse position to 1000 units away)
AND
have a clamp on their rotations so they aren’t allowed to rotate as far as they please to follow the ray.

The BAD:
What did seem to happen was, that at certain angles, the turrets wobble slightly around. I’m guessing it’s got to do with those spots like 180 or so when the euler angles invert.

Any ideas on this? How to fix, or if my code is completely inneficient and are better ways to achieve this?

Thanks.

private var targetrange:float = 1000.0;
var anglelimit = 20;


function Update () {

	var ray : Ray = Camera.main.ScreenPointToRay(Vector3(Input.mousePosition.x,Input.mousePosition.y,0));
	var rayHit : RaycastHit;
	
	Debug.DrawRay(ray.origin, ray.direction * targetrange, Color.yellow);

	var rot = Quaternion.LookRotation(ray.GetPoint(targetrange) - transform.position, transform.up);

	var xbaseangle = transform.parent.rotation.eulerAngles.x;
	var ybaseangle = transform.parent.rotation.eulerAngles.y;
	var zbaseangle = transform.parent.rotation.eulerAngles.z;
	
	var rotationX = rot.eulerAngles.x;
	var rotationY = rot.eulerAngles.y;
	
	var xlimiter : float = Mathf.Clamp(Mathf.DeltaAngle(xbaseangle, rotationX), -anglelimit, anglelimit);
	var ylimiter : float = Mathf.Clamp(Mathf.DeltaAngle(ybaseangle, rotationY), -anglelimit, anglelimit);

	transform.rotation = Quaternion.Euler(xbaseangle,ybaseangle,0) * Quaternion.Euler(xlimiter,ylimiter,0);

	transform.localRotation.eulerAngles.z = 0;

	print(xbaseangle +"     "+ ybaseangle);
}