Selected enemy off camera

Selected enemy off camera

I'm facing a problem with a game I'm making.
Currently I can select an enemy and mark it as shown on the image: 
But now I want to show the position of the selected enemy on the screen when it's off camera.
So my questions are: 

How do I know when an enemy is off camera.
How can I show in GUI an arrow on the edge of the screen that points to the position of that enemy. Perhaps something related to what I did to point towards the crosshair?

Vector3 positionOnScreen = Camera.main.ScreenToWorldPoint(mousePos + Vector3.forward * range);
Vector3 targetDir = positionOnScreen - transform.position;

Thanks!

Solutions/Answers:

Answer 1:

  1. You can easily know if a world point is visible by a given camera using Camera.WorldToViewportPoint. This will return a Vector2 that represents the position of your object in the viewport. A viewport goes from [0,0] (bottom left) to [1,1] (top right). If the returned value has a component lower than 0 or higher than 1 it means that the object is offscreen (or partially offscreen).

  2. As Seyed Morteza Kamali suggested in his comment, you can point the position of your object using basic intersection


About the second point the solution is all about linear function (y = ax + b).

            Vector2 a = viewport_pos; // viewport position of your offscreen item
            Vector2 b = target_viewport_pos; // viewport position of the target (in your case 0.5;0.5 for the 

            if (b.x == a.x || a.y == b.y) return;

            // y = px + d
            float p = (b.y - a.y) / (b.x - a.x);
            float d = a.y - p * a.x;

            float new_vy;
            float new_vx;

            // Check the axis with the biggest difference to define on which side of the screen you should display the arrow.
            float diff_x = a.x - b.x;
            float diff_y = a.y - b.y;

            // Display the arrow on the left/right sides
            if (diff_x > diff_y)
            {
                new_vx = viewport_pos.x < 0 ? 0f : 1f;
                new_vy = new_vx * p + d;
            }
            else // Display the arrow on the top/down sides
            {
                new_vy = viewport_pos.y < 0 ? 0f : 1f;
                new_vx = (new_vy - d) / p;
            }

            // This is the position of your arrow.
            Vector3 new_pos = Camera.main.ViewportToWorldPoint(new Vector3(new_vx, new_vy));
```

References