Maths problems are the worst, and how I added a pointer arrow to a moving target

The biggest criticism of my recent game (other than it being a shit game about shit) was that it was difficult to find the enemy turd in level 1.

I thought that the best solution for this would be to add an arrow pointing in the direction of the enemy, to follow. I’ve seen this in so many games that I assumed it would be dead easy to add. Something like this:

arrow to target

Turns out I was wrong.

Or maybe it’d be easy if I was better at mathematics. But for me this was a hard one to solve. Knowing that my grasp of maths is worse than the average gym instructor, I trawled the internet for help. Luckily Unity’s community is large and this question has been asked many times. However every answer I found seemed to be lacking something, and wouldn’t work for me. Possibly because I was adding my arrow to the UI layer (and I’m not changing that because it’s sensible. Sensible goddammit!) meaning that the axis is different – my gameObjects rotate on the y-axis, but I wanted the arrow to rotate on its z-axis.

Anyway, despite spending a lot of time in Unity Answers, and posting the question twice but slightly differently worded (I was getting desperate) it was a Facebook comment where I got a good link to a solution. Here’s the solved formula:

//--point arrow to enemy
var dir = transform.position - target.transform.position;
var angle = Mathf.Atan2(dir.z, dir.x) * Mathf.Rad2Deg;
arrow.transform.rotation = Quaternion.AngleAxis(angle+90, Vector3.forward);

So thanks Regan No, and the link he sent: http://answers.unity3d.com/questions/654222/make-sprite-look-at-vector2-in-unity-2d-1.html

This means I can rotate the arrow around the center of the screen. Now quite attached to the edge, like I wanted. But good enough!

Making the arrow hide when close to the enemy

I wanted to hide the arrow when it got too close, as it’s then useless. So faded it out. Here’s the full script (or see it on GitHub):

var target : GameObject; // GameObject to point to
var arrow : GameObject;
private var angle : float;
var fadeSpeed : float = .05;
var amt : float = 0;
var distanceToTarget : float;

function Start() {
   arrow.GetComponent.<CanvasGroup>().alpha = 0;
}

function Update() {
   //--point arrow to enemy
   var dir = transform.position - target.transform.position;
   var angle = Mathf.Atan2(dir.z, dir.x) * Mathf.Rad2Deg;
   arrow.transform.rotation = Quaternion.AngleAxis(angle+90,    Vector3.forward);

   //--get distance
   distanceToTarget = Vector3.Distance(transform.position, target.transform.position);

   if(distanceToTarget < 4.5){
      //--fade out
      if(amt > 0){
         amt -= fadeSpeed;
      }
   } else {
      //--fade in
      if(amt < 1){
         amt += fadeSpeed;
      }
   }

   arrow.GetComponent.<CanvasGroup>().alpha = amt;
}

You can download this game on IndieDB.