I am making a Line of Sight (LOS) system using a mesh.
The mesh is partially working. It works in the sense that it detects collisions with the raycast.point however the raycast.point does not align with the actual mesh.
I’m at a bit of a loss as to what’s happening, as any changes I make makes it worse and/or breaks it.
Any help would be greatly appreciated!
[SerializeField] Rigidbody rb;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
Vector3 origin = Vector3.zero;
Mesh mesh = new Mesh();
GetComponent<MeshFilter>().mesh = mesh;
float fov = 90f;
int rayCount = 50;
float angle = 0f;
float angleIncrease = fov / rayCount;
float viewDistance = 50f;
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;
for (int i = 0; i <= rayCount; i++)
{
Vector3 vertex = origin + GetVectorFromAngle(angle) * viewDistance;
RaycastHit rayCastHit;
Physics.Raycast(origin, GetVectorFromAngle(angle) * viewDistance, out rayCastHit);
Debug.DrawRay(origin, GetVectorFromAngle(angle) * viewDistance, Color.blue);
if (rayCastHit.collider == null)
{
Debug.Log("no hit");
vertex = origin + GetVectorFromAngle(angle)* viewDistance;
}
else
{
Debug.Log("hit");
vertex = rayCastHit.point;
}
vertices[vertexIndex] = vertex;
if (i > 0)
{
triangles[triangleIndex + 0] = 0;
triangles[triangleIndex + 1] = vertexIndex - 1;
triangles[triangleIndex + 2] = vertexIndex;
triangleIndex += 3;
}
vertexIndex++;
angle -= angleIncrease;
}
mesh.vertices = vertices;
mesh.uv = uv;
mesh.triangles = triangles;
}
public static Vector3 GetVectorFromAngle(float angle)
{
float angleRad = angle * (Mathf.PI / 180f);
return new Vector3(Mathf.Cos(angleRad), 0, Mathf.Sin(angleRad));
}
For me your code works as long as the gameobject with the script has position (0,0,0), scale (1,1,1) and rotation (0,0,0).
If you want it to work with any position, you need to keep in mind that Physics.Raycast works in world space while vertex positions are in local space (coordinates are relative to the gameobject).
I modified your code to allow moving it:
[SerializeField] Rigidbody rb;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
Vector3 origin = transform.position;//MODIFICATION: gameobject's position in world space
Mesh mesh = new Mesh();
GetComponent<MeshFilter>().mesh = mesh;
float fov = 90f;
int rayCount = 50;
float angle = 0f;
float angleIncrease = fov / rayCount;
float viewDistance = 50f;
Vector3[] vertices = new Vector3[rayCount + 1 + 1];
Vector2[] uv = new Vector2[vertices.Length];
int[] triangles = new int[rayCount * 3];
vertices[0] = Vector3.zero;//MODIFICATION: this is in local space
int vertexIndex = 1;
int triangleIndex = 0;
for (int i = 0; i <= rayCount; i++)
{
Vector3 vertex;//MODIFICATION
RaycastHit rayCastHit;
bool hit = Physics.Raycast(origin, GetVectorFromAngle(angle) * viewDistance, out rayCastHit);
Debug.DrawRay(origin, GetVectorFromAngle(angle) * viewDistance, Color.blue);
if (!hit)//MODIFICATION: recommended way to check if the raycast hit something
{
Debug.Log("no hit");
vertex = GetVectorFromAngle(angle) * viewDistance;//MODIFICATION: local space, relative to this gameobject
}
else
{
Debug.Log("hit");
vertex = rayCastHit.point - origin;//MODIFICATION: subtract origin to get into local space
}
vertices[vertexIndex] = vertex;
if (i > 0)
{
triangles[triangleIndex + 0] = 0;
triangles[triangleIndex + 1] = vertexIndex - 1;
triangles[triangleIndex + 2] = vertexIndex;
triangleIndex += 3;
}
vertexIndex++;
angle -= angleIncrease;
}
mesh.vertices = vertices;
mesh.uv = uv;
mesh.triangles = triangles;
}
public static Vector3 GetVectorFromAngle(float angle)
{
float angleRad = angle * (Mathf.PI / 180f);
return new Vector3(Mathf.Cos(angleRad), 0, Mathf.Sin(angleRad));
}