Ok hi again guys, I already got it ^^. So the suggestion by @zulo3d is what I used, the idea is to use Physics.OverlapSphere to create a circle around the player and set a maximum angle to get the enemies.
I used this video to make the calculations and the debug to be able to see what is happening, but needed to change a lot, keeping only the basis of logic.
First the code gets an array containing all colliders it gets inside of the circle. Then I loop through each one of the colliders and check if the position of the collider is inside the angle that I set, then it creates a raycast between the player and the monster, checking if theres a wall.
if theres no wall then I put the transform component inside a list of transform. In the end of the iteration I return the list
public List<Transform> FieldOfViewCheck()
{
Collider[] rangeChecks = Physics.OverlapSphere(player.position, radius, targetMask);
//The list containing the transforms of monster I can shoot
List<Transform> monsters = new List<Transform>();
//Did I find any monster
if (rangeChecks.Length != 0)
{
for(int i = 0; i < rangeChecks.Length; i++)
{
//Take it transform
Transform target = rangeChecks[i].transform;
Vector3 directionToTarget = (target.position - player.position).normalized;
//If the angle between my vector3 Pos and the vector3 of the monster is less than half of the angle I defined in the inspector (So we're checking if the difference still inside the boundaries that I set)
if (Vector3.Angle(player.forward, directionToTarget) < angle / 2)
{
float distanceToTarget = Vector3.Distance(player.position, target.position);
//Instead of checking for a monster I'm checking for a wall, If I dont see a wall then we are seing the monster
if (!Physics.Raycast(player.position, directionToTarget, distanceToTarget, obstructionMask))
monsters.Add(target);
}
}
}
return monsters;
}
at the gun script I do a loop through all the transforms and check one by one which one is closer, after this loop I create a raycast between the gun and the zombie, and if the raycast hits we use the Get.Component<>() to do damage in the zombie.
public void Shoot()
{
RaycastHit hit;
List<Transform> monsters = fieldOfView.FieldOfViewCheck();
if (monsters.Count != 0)
{
float distanceToTarget;
float leastDistanceToTarget = fieldOfView.radius;
Transform monsterTarget = monsters[0].transform;
//Loop through all the monster found in fieldOfViewCheck()
for (int i = 0; i < monsters.Count; i++)
{
//Do the distance between the gun and the monster
distanceToTarget = Vector3.Distance(firePoint.position, monsters[i].position);
//if the distance is less than the distance of the other zombie (in the first iteration it need to be less than the radius)
if (distanceToTarget < leastDistanceToTarget)
{
leastDistanceToTarget = distanceToTarget;
monsterTarget = monsters[i];
}
}
Vector3 directionToMonster = (monsterTarget.position - firePoint.position).normalized;
var raycast = Physics.Raycast(firePoint.position, directionToMonster, out hit, leastDistanceToTarget, whatIsMonster);
if (raycast)
{
Monster monster = hit.transform.GetComponent<Monster>();
if (monster != null)
{
monster.TakeDamage(damage);
}
}
}
}
As u read the code checks with an sphere, loop through all the components inside the range checking for a wall using raycast, then loop again check every distance between the player and the zombie, and after all of that it gets the zombie component. So if u guys have any idea to make this more fast I would appreciate.
Anyway I made this fairly fast because comp-3 video, but I still need to be able to check for multiple targets for some type of weapons, like a double barrel.
j26u3q
I already made this reusable, with a pistol and a sniper, each one having different damage, range, and angle. By theres more room for improvement, for now I need to have a way to change guns without the need to change in the inspector, and a way to get the player transform too (using scriptable objects is worth? i did this with the zombies)
I might do a video about this.