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
3 Answers
3
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.
Awesome! I love your solution :)
– StatementThank! On an unrelated note, I wouldn't understand IENumerator syntax in javascript if it wasn't for one of your answers :)
– PrimeDerektiveOh, hehe. :) Give and recieve. What I love about hanging about unity answers is that you learn these other ways of achieving the same thing, and I think using Vector3.Angle is far more self explainatory than using dot products. I am on a quest to try and find simpler alternatives to just about anything, and I love the progress so far.
– StatementThis sounds very interesting. The part where you say "You want to calculate the direction between the enemy and the player", how would you about doing this? What if there is more than one enemy in the scene?
– anon87078182If you click the link I put in my answer, you'll see the line "var targetDir = target.position - transform.position;" thats how you'd do it (target would be the player object). You would have this script on every enemy, so every enemy would be calculating their own direction and FoV angle to the player.
– PrimeDerektive