Rotating Turret Algorithm

Hi all,

I want a turret in my top down 2D game that tracks and rotates to point in the direction of my player. I managed to come up with a working method, using trigonometry to work out the angle, which I then use LerpAngle to smoothly rotate towards, as follows:-

float TrackPlayer(Vector2 from, Vector2 to)
	{
		float adjacent;
		float opposite;
		float angle;
		
		adjacent=Mathf.Abs(from.x-to.x);
		opposite=Mathf.Abs(from.y-to.y);
		angle=Mathf.Atan2(adjacent,opposite)*Mathf.Rad2Deg;
		if (from.y>to.y)angle=180-angle;
		if (from.x<to.x)angle=360-angle;
		
		return angle;
	}

In the above, from would be my turret position and to would be my player position.

But I can’t help thinking that this looks a bit clunky and there must be a built in function that’s probably more efficient, however I can’t for the life of me find it.

Can anyone suggest something better, or should I just stick with what I’ve got?

Thanks :slight_smile:

You probably want Transform.LookAt()

http://docs.unity3d.com/Documentation/ScriptReference/Transform.LookAt.html

transform.LookAt() is 3D not 2D
but if LookAt() is what you are searching for, then you can use

transform.LookAt(new Vector3(target.position.x , target.position.y , transform.position.z));

for the same funktionality in 2D

Thanks for the answers, I did look at transform.LookAt initially, but as Dave xP says, it is a 3D command and produces unwanted rotation on the x and y axis.

Once I’ve used transform.Lookat is there a way to set the x and y rotation components of the transform.rotation to zero?

I’ve tried transform.rotation.x=0, and transform.rotation.y=0, but this doesn’t work, I assume because quaternions don’t work like that.

If I can solve this part of the puzzle then I can make use of transform.LookAt.

Well, I’ve googled ‘unity 2D version of transform.lookat’ and lots of people having the same problem, without a solution that works for me as far as I can see.

So I think all things considered I’m going to stick with what I have for now, it might be ugly but it works.

Thanks for the input guys. :slight_smile:

Why not use the LookAt() overload that takes a Vector3 arg (as mentioned by Dave xP above) and reset whatever components you want to?

I had already tried that, using Vector3.Forward, the trouble was I couldn’t work out how to cancel out the x,y rotation afterwards.

But, I just worked it out after a bit more googling gave me a clue.

Although I said I’d given up, I didn’t (I hate being beaten :slight_smile: ) and I came up with this, which seems to work how I want.

transform.LookAt(Target.position,Vector3.forward);
transform.eulerAngles = new Vector3(0, 0, -transform.eulerAngles.z);

Thanks again guys :slight_smile:

So final TrackPlayer Method is now:-

	void TrackPlayer()
	{
		Quaternion rot=transform.rotation;
		transform.LookAt(player,Vector3.forward);
		transform.eulerAngles = new Vector3(0, 0, -transform.eulerAngles.z);
		desiredRotation=transform.rotation;
		transform.rotation=rot;

		Invoke("TrackPlayer",trackFrequency);
	}

and in the Update() Function I use this to smoothly turn the turret:-

transform.rotation=Quaternion.Lerp(transform.rotation,desiredRotation,turnSpeed * Time.deltaTime);