- Home /
Visual debugging a Field of view angle
I've been trying for the past few days trying to figure out a way to visual debug a field of view angle. I've tried it multiple ways with a custom editor and a mesh but its too confusing for me. Is there a simpler way to do this? I have this field of view script for enemies to see the player. Everything works fine, but I could really use the debug to figure out view ranges.
I'll post the code below:
void Update () {
inCell = player.GetComponent<PlayerMovement> ().playerInCell;
if(inCell == true)
{
Patrol ();
}
else
{
CheckForLights ();
FieldOfView ();
//Debug.Log ("A luz da cena está: " + sceneLightStatus + " e o player tem a luz: " + playerLightStatus);
if(playerInSight == true && playerInRange == true)
{
inPursuit = true;
agent.SetDestination (target.transform.position);
}
else
{
Patrol ();
}
}
}
void FixedUpdate()
{
Vector3 raycastDirection = target.transform.position - transform.position;
RaycastHit hit;
if(Physics.Raycast (transform.position, raycastDirection, out hit, viewDistance) && hit.transform.tag == "Player")
{
playerInRange = true;
}
else{
Invoke ("ChangePlayerInRange", exitTime);
}
}
void FieldOfView()
{
Vector3 targetDir = target.position - transform.position;
float angle = Vector3.Angle (targetDir, transform.forward);
minimumDistance = Vector3.Distance (target.transform.position, transform.position);
if(angle < FOV * 0.5f && minimumDistance > 2f)
{
playerInSight = true;
}
else if(minimumDistance < 2f){
playerBusted = true;
playerInSight = true;
}
else{
Invoke ("ChangePlayerInSight", exitTime);
//playerInSight = false;
}
}
Answer by Bunny83 · Feb 13, 2018 at 10:56 PM
Well the field of view of your enemy is actually a cone. So if you want to create a mesh that visually shows that cone you just need something like this:
public Mesh CreateViewCone(float aAngle, float aDistance, int aConeResolution = 30)
{
Vector3[] verts = new Vector3[aConeResolution +1];
Vector3[] normals = new Vector3[verts.Length];
int[] tris = new int[aConeResolution * 3];
Vector3 a = Quaternion.Euler(-aAngle, 0, 0) * Vector3.forward * aDistance;
Vector3 n = Quaternion.Euler(-aAngle, 0, 0) * Vector3.up;
Quaternion step = Quaternion.Euler(0, 0, 360f / aConeResolution);
verts[0] = Vector3.zero;
normals[0] = Vector3.back;
for (int i = 0; i < aConeResolution; i++)
{
normals[i+1] = n;
verts[i+1] = a;
a = step * a;
n = step * n;
tris[i * 3] = 0;
tris[i * 3 + 1] = (i + 1) % aConeResolution + 1;
tris[i * 3 + 2] = i+1;
}
Mesh m = new Mesh();
m.vertices = verts;
m.normals = normals;
m.triangles = tris;
m.RecalculateBounds();
return m;
}
Note that "aAngle" would also be half your FOV angle. "aDistance" defines how far you want to draw the cone. Note it's the side length of the cone, not its height. The "aConeResolution" defines how many points the cone should have. The more points the smoother the cone base, Also note that the cone is not "closed" at the end. So the "base circle" is missing.
The cone mesh is aligned with the local forward axis. So as long as the FOV angle doesn't change you only need to create the cone mesh once. If you add the renderer to the enemy it will always show it's FOV.
Thank you so much for the answer! I understand what you did but how do I apply the renderer now? It has to be to a child of the enemy right?
Edit: I created an empty child with a mesh renderer and a mesh filter in it. Then, in my main script I created a public mesh filter variable, and then in the editor I assigned the mesh filter from the child to the parent. In the script I tried multiple things and what worked better was this line in the Start method, but I still can't see anything, even though I can see a mesh being applied to the child, in the editor.
meshFilter.mesh = CreateViewCone (FOV, viewDistance, coneResolution);
I figured it out. It seems the empty child I was using was too small, and I had to scale it to 100. I think it might have to do from the objects I imported from maya, which suffered an 0.01 scale. I don't know why this happens, I set the units in maya and the scale factor in unity to match (technically), but it happened anyway. Thanks!