You've made the same mistake as in this previous question: Why is Raycast hitting a masked layer?
Paraphrasing/quoting my answer there:
The problem is that raycast functions have so darned many optional parameters, and LayerMask
isn't picky about what type it's treated as.
From the docs:
public static RaycastHit2D Raycast(
Vector2 origin,
Vector2 direction,
float distance = Mathf.Infinity,
int layerMask = DefaultRaycastLayers,
float minDepth = -Mathf.Infinity,
float maxDepth = Mathf.Infinity
);
layerMask
is the fourth parameter. So if you provide only three parameters, Unity wants to interpret them as origin, direction, and distance.
It might seem like providing an input of type LayerMask
should make your intent unambiguous, or at least generate a compile-time error, but LayerMask
can implicitly convert to int
, and int
can implicitly convert to float
.
So when you put a LayerMask in the third argument, the compiler tries to convert it to a float, succeeds, and so silently re-interprets your mask as a distance.
If your mask evaluates to a small number, like say 1, then you get a very short ray that misses your player. If it evaluates to a large number, you might get a ray long enough to hit the player, but along the way it hits something on a non-player layer (since the function thinks you provided no layer mask), and returns that instead.
You can fix this by providing a dummy distance value (say, infinity, if you don't have any more conservative upper bound) so your layer mask selections end up in the fourth argument where Unity expects it:
RaycastHit2D raycastHit2D = Physics2D.Raycast(enemyEyes.transform.position, new Vector2(directionOfRay, 0), float.positiveInfinity, LayerMask.GetMask("Player"));
.CompareTag()
instead of.tag ==
for better performance. \$\endgroup\$