I have been following this tutorial to make a ‘field of view cone’ for NPCs. The tutorial was made for 2D games but adapting it to 3D has been fairly straightforward except for this problem I cannot seem to solve.
The problem happens whenever the game object is not centered at (0,0,0) the mesh will be much further in any direction than the physics and debug rays. I have attached some pictures showing what happens when you move the game object and the code I’m working with below.
Is there something that governs the movement of the mesh on the game object that I am not aware of?
Here is the game running when the game object is at the origin.
This happens when I move the game object in the negative X direction
This will happen when I move the game object in the positive Z direction
This will happen when I move the game object in the positive Y direction
The fov is made from an empty game object that is given a script, a material, a mesh filter, and a mesh renderer.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FieldOfView : MonoBehaviour {
[SerializeField] private LayerMask layerMask;
private Mesh mesh;
private Vector3 origin;
private float startingAngle;
private float fov;
private void Start()
{
mesh = new Mesh();
GetComponent<MeshFilter>().mesh = mesh;
fov = 90f;
}
private void LateUpdate()
{
int rayCount = 50;
float angle = startingAngle;
origin = transform.position;
Vector3 eyeHeight = Vector3.zero; //new Vector3(0, 2.5f, 0);
float angleIncrease = fov/rayCount;
float viewDistance = 10f;
Vector3[] vertices = new Vector3[rayCount + 1 + 1];
Vector2[] uv = new Vector2[vertices.Length];
int[] triangles = new int[rayCount * 3];
vertices[0] = origin;
int vertexIndex = 1;
int triangleIndex = 0;
RaycastHit raycastHit;
for (int i = 0; i <= rayCount; i++)
{
Vector3 vertex;
// RayCast(Origin, Direction, MaxDistance, LayerMask, QueryTriggerInteraction)
Physics.Raycast(origin + eyeHeight, GetVectorFromAngle(angle), out raycastHit, viewDistance, layerMask);
Debug.DrawRay(origin + eyeHeight, GetVectorFromAngle(angle)*viewDistance,Color.blue,0,true);
if(raycastHit.collider == null)
{
// object was not hit
Debug.Log("No Hit");
vertex = origin + GetVectorFromAngle(angle)* viewDistance;
}
else
{
// object was hit
Debug.Log("Hit");
Debug.Log(raycastHit);
// raycastHit.point.y = 0;
//vertex = raycastHit.point
vertex = Vector3.Scale(raycastHit.point, new Vector3(1,0,1));
}
vertices[vertexIndex] = vertex;
if(i > 0)
{
triangles[triangleIndex + 0] = 0;
triangles[triangleIndex + 1] = vertexIndex -1;
triangles[triangleIndex + 2] = vertexIndex;
triangleIndex += 3;
}
vertexIndex++;
// this is not += because increasing in angle in unity goes clockwise instead of counterclockwise
angle -= angleIncrease;
}
triangles[0] = 0;
triangles[1] = 1;
triangles[2] = 2;
mesh.vertices = vertices;
mesh.uv = uv;
mesh.triangles = triangles;
}
Vector3 GetVectorFromAngle(float angle)
{
float angleRad = angle * (Mathf.PI/180f);
return new Vector3(Mathf.Cos(angleRad), 0, Mathf.Sin(angleRad));
}
float GetAngleFromVectorFloat(Vector3 direction){
direction = direction.normalized;
float n = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
if (n < 0 ) n += 360;
return n;
}
//when on a NPC object the NPC will call this function
public void SetOrigin(Vector3 origin)
{
this.origin = origin;
}
//when on a NPC object the NPC will call this function
public void SetAimDirection(Vector3 aimDirection)
{
startingAngle = GetAngleFromVectorFloat(aimDirection) - fov / 2f;
}
}