Best way to detect enemies that player is looking at?

I’m trying to create a combat system somewhat similar to the Batman Arkham games and need to identify the enemy the player is trying to target. I have a screen centred player, with many enemies that surround them. They are in a 3D space, but we’re not really using the Y axis. I want to attack the enemy that is closest to the direction the player is pushing on the left stick. What would be the most accurate and performative way to achieve this?

I’ve considered a raycast, but I feel it would be too easy to miss, if I used a sphere/boxcast I could widen the cast, but then if we hit multiple enemies I wouldn’t know how to define which one was the most in line with the players input.

Ideally I want to detect everything within a cone shape, but then pick the enemy most in the centre line of the cone.

Any ideas or suggestions on this would be most appreciated, thank you.

  1. Determine Player Input Direction:
  • Get the input direction from the left stick of the controller. This will give you a vector indicating the direction in which the player is pushing.
  1. Perform a Cone or Field of View Check:
  • Create a cone or field of view in the direction of the player’s input. You can define this cone using an angle that represents the acceptable range of targeting.
  • For each enemy in your scene, perform a raycast from the player’s position in the direction of the enemy. You can use Physics.Raycast or Physics.RaycastAll.
  1. Calculate the Angle Between Input and Enemy Direction:
  • For each enemy that the raycast hits, calculate the angle between the player’s input direction and the direction vector from the player to the enemy.
  • You can use Vector3.Angle to compute this angle.
  1. Choose the Closest Enemy:
  • Track the closest enemy by keeping a variable that stores the minimum angle encountered so far and the associated enemy.
  • Compare the angles calculated in step 3, and if an angle is smaller than the current minimum angle, update the minimum angle and associated enemy.
  1. Attack the Chosen Enemy:
  • Once you’ve iterated through all enemies, you will have the enemy that is closest to the player’s input direction.
  • You can then initiate an attack on this chosen enemy.

it just an example of code

public Transform player;
public float targetingAngle = 45f; // The acceptable targeting angle

void Update()
{
Vector3 inputDirection = /* Get the input direction from the left stick */;
Transform closestEnemy = null;
float minAngle = Mathf.Infinity;

foreach (var enemy in allEnemies)
{
    Vector3 directionToEnemy = enemy.position - player.position;
    float angle = Vector3.Angle(inputDirection, directionToEnemy);

    if (angle <= targetingAngle)
    {
        if (angle < minAngle)
        {
            minAngle = angle;
            closestEnemy = enemy;
        }
    }
}

if (closestEnemy != null)
{
    // Attack the closestEnemy
}

}

Thank you so much for such a thorough response. I’ve been really struggling the last couple of days to calculate the angle between each enemy and the player. I’ve been trying to use Vector3.angle, but I think I’m misunderstanding something as it’s not been working. I’m not in a position to try and implement your suggestion right now but should hopefully be able to give it a try within the next couple of days.