- Home /
Create Vision Cone for Torch Effect Using Mesh
I have a 2D platformer, and I have a player, a tilemap, and a black overlay with a mask around the player. What I've been trying to do is cast out rays to make a mesh which I can use to mask away the black overlay where it intersects the mesh. However, the raycasts don't seem to be interacting with the tilemap correctly. However, if I disable the tilemap, the raycasts work fine (but the rays have nothing to hit so I don't know if even that is fine).
Images (background walls disabled for visibility - they have no effect on the issue):
Player starts at (0, 0), but I moved him up to show the problem.
With the midground tiles disabled (the layer which the rays interact with), the mesh 'fixes' itself. Note that the camera had no effect (which was my first suspicion)
The script in question is FieldOfView, and here is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FieldOfView : MonoBehaviour
{
[SerializeField] LayerMask layerMask;
Mesh mesh;
float fov;
float viewDistance;
Vector3 origin;
void Start()
{
mesh = new Mesh();
GetComponent<MeshFilter>().mesh = mesh;
fov = 90f;
Vector3 origin = new Vector3(0, 0, 0);
viewDistance = 6f;
}
void Update()
{
int rayCount = 10;
float angle = 0f;
float angleIncrease = fov / rayCount;
Vector3[] vertices = new Vector3[rayCount + 2];
Vector2[] uv = new Vector2[rayCount + 2];
int[] triangles = new int[rayCount * 3];
vertices[0] = origin;
int vertexIndex = 1;
int triangleIndex = 0;
for(int i = 0; i <= rayCount; i++)
{
Vector3 vertex;
RaycastHit2D raycastHit2D = Physics2D.Raycast(origin, GetVectorFromAngle(angle), viewDistance, layerMask);
if(raycastHit2D.collider == null)
{
// miss object
vertex = origin + GetVectorFromAngle(angle) * viewDistance;
} else
{
// hit object
vertex = raycastHit2D.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;
mesh.bounds = new Bounds(origin, Vector3.one * 1000f);
}
public static Vector3 GetVectorFromAngle(float angle)
{
// angle = 0 -> 360
float angleRad = angle * Mathf.Deg2Rad;
return new Vector3(Mathf.Cos(angleRad), Mathf.Sin(angleRad));
}
public static float GetAngleFromVectorFloat(Vector3 dir)
{
dir = dir.normalized;
float n = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
if (n < 0) n += 360;
return n;
}
}
Project Files Here.