How to Detect all gameobjects(i.e. enemies) in field of view?

Hi to all
I,m currently working on a simple animal ai script that include ai sight and ai hearing. i want ai objects be able to see all enemies in desired distance and desired field of view in front of it.i know by using raycastall function i can get all hitted colliders in a direction but if in example i want field of view be 120 deg so it must be like a cone in front of animal that scan 60 deg right from forward direction to 60 deg left of forward direction.
HERE IS PROBLEM:
how i can create a rotation -60 deg leftside of forward direction?because when write like this code:
quaternion rot=quaternion.angleaxis(vector3.up,-60);
then rot.eaulerangles will be (0,300,0) not (0,-60,0);
please help me.
thanks.

3 Answers

3

Try something like this:

    Quaternion startingAngle = Quaternion.AngleAxis(-60, Vector3.up);
    Quaternion stepAngle = Quaternion.AngleAxis(5, Vector3.up);

    ...

    void DetectThings()
    {
         RaycastHit hit;
         var angle = transform.rotation * startingAngle;
         var direction = angle * Vector3.forward;
         var pos = transform.position;
         for(var i = 0; i < 24; i++)
         {
             if(Physics.Raycast(pos, direction, out hit, 500))
             {
                 var enemy = hit.collider.GetComponent<Enemy>();
                 if(enemy)
                 {
                      //Enemy was seen
                 }
             }
             direction = stepAngle * direction;
         }
    }

This has the benefit of only running 24 raycasts, but as they diverge it might oddly miss and hit enemies that are far away.

Your other choice is to keep a list of enemies and see if their centre mass (or a collection of other points) can be seen/

#Enemy.cs

   using System.Collections;
   using UnityEngine;
   using System.Collections.Generic;

   
   public class Enemy : MonoBehaviour
   {
         public static List<Collider> allEnemyColliders = new List<Collider>();
         void OnEnable()
         {
              if(collider)
                  allEnemyColliders.Add(collider);
         }
         void OnDisable()
         {
              if(collider)
                 allEnemyColliders.Remove(collider);
         }
   }

Now you can test the angle to each of the enemies using a foreach loop over allEnemyColliders and use the Dot product or Vector3.Angle (using the transform.forward of the interested animal dot the vector direction to each enemy) to get whether it is in your view cone. And use Collider.Raycast to check if that particular enemy can be seen when it’s in the cone. This has the advantage of only doing the number of raycasts for in range enemies at the expense of working that out, but will not suffer from diverging raycasts.

i test a small modified version of your code with 3dp controller and result wasn't correct,where hit points weren't in front of player,instead were rightside, lokk to test snapshot bellow: why this happend? [11083-test+ai+detect.jpg|11083]

problem solved. i modify line 1 in your code to afew tilt around x axis for top down scan like this snippet: startingAngle=Quaternion.AngleAxis(tiltAroundX,Vector3.right); but it was incorrect, so i chanche your code to this and wow it work perfectly : Quaternion startingAngle = Quaternion.Euler(tiltAroundX,-sightangle,0); thanks a lot :--) below is new snapshot:[11084-corrected+test.gif|11084]

Could you use a collider? Parent one to the front of your animal and check if it hits an enemy?

thanks for reply but my question is how i can scan field of view(60 deg in right to 60 deg in left of view) in every frame and get all colliders in range? indeed i want cast a ray in a direction that move on an circumference from right to left where ai boject that run script is in center of circle.

I think it might be better to do this “the other way around”. For each enemy, compute the direction from the animal to the enemy. Then take the dot product between this direction and the animals forward vector. This will give you a value that’s related to the cos of the angle between the vectors. If this value is less than cos60, then the enemy is within sight of the animal. Rather than do this calculation for every enemy every frame, you may want to manage a list of visible objects, and periodically check whether an enemy has come into, our out of sight.

Thanks for answer,but since i am working on an animal sight and there isn't any obvious enemy so i can't use enemy position and angle.(indeed i have two animal type:wild and domestic,where wilds attack domestics and domestic escape from wild.all animals free roaming around terrain and any AI animal in realtime can be enemy or not.) if i can get all animals around current object then with checking race property of them, i can do right action like scape or attack.

You did use the word "enemy" in your question :P