So in my project I have code that is used as a FOV/FOW. It is supposed to be able to be affected and collide with objects, but it does not work. And looks like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;
public class FieldOfViewScript : NetworkBehaviour {
[SerializeField] private LayerMask layerMask;
private Mesh mesh;
private float fov = 90f;
private float viewDistance = 5f;
private Vector3 origin;
private float startingAngle = 0f;
void Start() {
mesh = new Mesh();
GetComponent<MeshFilter>().mesh = mesh;
origin = transform.position;
}
void LateUpdate() {
int rayCount = 50;
float angle = startingAngle;
float angleIncrease = fov / rayCount;
Vector3[] vertices = new Vector3[rayCount + 2];
int[] triangles = new int[rayCount * 3];
vertices[0] = Vector3.zero;
for (int i = 0; i <= rayCount; i++) {
float angleRad = angle * Mathf.Deg2Rad;
Vector3 dir = new Vector3(Mathf.Cos(angleRad), Mathf.Sin(angleRad));
RaycastHit hit;
Vector3 vertex;
if (Physics.Raycast(origin, dir, out hit, viewDistance, layerMask)) {
vertex = hit.point - origin;
} else {
vertex = dir * viewDistance;
}
vertices[i + 1] = vertex;
if (i < rayCount) {
triangles[i * 3] = 0;
triangles[i * 3 + 1] = i + 1;
triangles[i * 3 + 2] = i + 2;
}
angle -= angleIncrease;
}
mesh.Clear();
mesh.vertices = vertices;
mesh.triangles = triangles;
}
}
You probably have non-identity scaled transforms somewhere in there. That’s where I would look first anyway. I dropped your script on a default Cube, then moved another default Cube into its fan, then rotated things until everything worked.
Time to start debugging!
By debugging you can find out exactly what your program is doing so you can fix it.
Use the above techniques to get the information you need in order to reason about what the problem is.
You can also use Debug.Log(...); statements to find out if any of your code is even running. Don’t assume it is.
Once you understand what the problem is, you may begin to reason about a solution to the problem.
Apologies, I was doing some miscalculations in my code. For those who are having trouble, here is my current script:
using UnityEngine;
using Mirror;
// This script renders the player's field of view (FOV) by casting rays and building a mesh.
// It works by casting multiple rays within a specified angle and distance,
// detecting objects within the FOV, and visualizing the area using a mesh.
public class FieldOfViewScript : NetworkBehaviour
{
// LayerMask to specify which layers the raycasts should check for collisions.
[SerializeField] private LayerMask layerMask;
// Total field of view angle in degrees.
[SerializeField] private float fov = 90f;
// Maximum distance the field of view extends.
[SerializeField] private float viewDistance = 5f;
// Option to display debug rays in the Scene view for visualization.
[SerializeField] private bool showDebugRays = true;
// The mesh used to visualize the field of view.
private Mesh mesh;
// Starting angle for the raycasts, adjusted to center the FOV.
private float startingAngle;
// Number of rays cast within the field of view; higher value increases mesh resolution.
[SerializeField] private int resolution = 100;
void Start()
{
// Initialize a new mesh and assign it to the MeshFilter component.
mesh = new Mesh();
GetComponent<MeshFilter>().mesh = mesh;
// Calculate the starting angle so that the FOV is centered around the player's facing direction.
startingAngle = -fov / 2f;
}
void LateUpdate()
{
// Number of rays to cast, based on the specified resolution.
int rayCount = resolution;
// Current angle starts at the starting angle.
float currentAngle = startingAngle;
// The incremental angle increase between each ray.
float angleIncrease = fov / rayCount;
// Arrays to store the mesh's vertices and triangle indices.
Vector3[] vertices = new Vector3[rayCount + 2]; // +2 to account for the origin and the last point.
int[] triangles = new int[rayCount * 3]; // Each triangle consists of 3 vertex indices.
// The origin point of the mesh is at the local position (0, 0, 0).
vertices[0] = Vector3.zero;
// Loop through each ray to cast.
for (int i = 0; i <= rayCount; i++)
{
// Convert the current angle from degrees to radians.
float angleRad = currentAngle * Mathf.Deg2Rad;
// Calculate the direction vector for the current angle.
Vector3 direction = new Vector3(Mathf.Cos(angleRad), Mathf.Sin(angleRad), 0f);
// Transform the local direction to world space, considering the object's rotation.
Vector3 worldDirection = transform.TransformDirection(direction.normalized);
// Perform a 2D raycast from the player's position in the calculated direction.
RaycastHit2D hit = Physics2D.Raycast(transform.position, worldDirection, viewDistance, layerMask);
// Variable to store the endpoint of the ray (either hit point or max view distance).
Vector3 finalPoint;
if (hit.collider != null)
{
// If the ray hit an object, set the final point to the hit location.
finalPoint = hit.point;
// Optionally draw the ray in the Scene view for debugging purposes.
if (showDebugRays)
Debug.DrawLine(transform.position, finalPoint, Color.red);
}
else
{
// If the ray didn't hit anything, set the final point to the maximum view distance.
finalPoint = transform.position + worldDirection * viewDistance;
// Optionally draw the ray in the Scene view for debugging purposes.
if (showDebugRays)
Debug.DrawLine(transform.position, finalPoint, Color.green);
}
// Convert the world space final point to local space relative to the player.
vertices[i + 1] = transform.InverseTransformPoint(finalPoint);
// After the first vertex, start defining triangles to build the mesh.
if (i < rayCount)
{
// Set the indices for each triangle.
triangles[i * 3] = 0; // First vertex is always the origin.
triangles[i * 3 + 1] = i + 1; // Current outer vertex.
triangles[i * 3 + 2] = i + 2; // Next outer vertex.
}
// Increment the angle for the next raycast.
currentAngle += angleIncrease;
}
// Clear any existing data from the mesh.
mesh.Clear();
// Assign the calculated vertices and triangles to the mesh.
mesh.vertices = vertices;
mesh.triangles = triangles;
// Recalculate the normals of the mesh for proper lighting and shading.
mesh.RecalculateNormals();
}
}