Hi,
I'm trying figure out the best way of creating a cone of vision for the enemies in my game. At first I was thinking of casting a number of rays to create a "cone" constantly and detect if they collide with the player, but I'm wondering if there is a faster method.
My other idea was to create a square collider which I could attach to my enemies and use isTrigger to pick up any collisions with the player.
Does anyone have any suggestions for better methods or any insight as to which way would be faster?
Thanks
You want to calculate the direction between the enemy and the player, get the forward vector of the enemy, and then use Vector3.Angle to calculate the angle.
Then you can check if the angle is less than whatever angle you want to be the enemy's field of vision (eg: a 20 degree cone, for instance), and if it is, then the player is in that enemy's field of vision.
See the Vector3.Angle docs for a good example:
http://unity3d.com/support/documentation/ScriptReference/Vector3.Angle.html
At first I was going to propose to use a frustum to check with, but then I noticed there is no Frustum class and no methods accepting a frustum in Physics methods. I guess you could go with Physics.OverlapSphere to make a broad test, then use dot product of the object relative with the direction the enemy is facing to determine if they see anything.
The overall idea would be:
- Test sphere overlap.
- Test dot product with delta vector to target and forward vector.
- If dot > 0.707 then within 90 degrees "field of view" = see target.
A sort of psuedo code:
if (target overlapping sphere)
{
direction = Normalize(target - this);
dot = Dot(direction, forward);
if (dot > 0.707)
{
I see target!
}
}
Or you could attach an empty gameobject above your AI’s head and name it sight and add this script to your ai’s main script
var sight : Transform;
var CanSee : boolean;
var Range = 100.0;
var Target : Transform;
function Update(){
sight.transform.LookAt(Target);
if(Physics.Raycast(sight.transform.position, sight.transform.forward, Range)
{
CanSee = false;
}
else {
CanSee = true;
}
}
now u can use the CanSee variable to decide whether to attack chase or do nothing.