Vision Cones for Unity3D

tool unity3d

Different vision cones created using the tool I developed, showing different styles and shapes
Different vision cones created using the tool I developed.

Why I made this tool

For a game I worked on at Voodoo, I implemented some AI behaviours for the enemy characters to allow them to look for weapons in the environment and to engage in combat with other characters. As I was developing that, I realised how difficult debugging these behaviours would be without a visual representation of what the enemies were seeing.

I couldn’t find an asset to draw a field of view vision cone that looked or behaved the way I wanted for this use, so I decided to write my own implementation using only the resources that the engine provides, with no external dependencies.

A field of view vision cone, which can be configured from the inspector, generated using Unity3D's Gizmos system.
A field of view vision cone, which can be configured from the inspector, generated using Unity3D's Gizmos system.

Creating a Vision Cone

The simplest approach I came up with in order to draw these vision cones was to split the shape into simpler ones: the sides of the cone, and its base. It doesn’t matter if the vision cone is 2D or 3D , this logic remains similar.

For the sake of simplicity, let’s stick to the implementation of a 2D vision cone, assuming that it is h tall and has a field of view of alpha degrees. Let’s also assume the vision cone will be placed at the origin of coordinates and will face the forward direction.

For the sides of the cone, drawing two lines that go from the origin to the corners of the vision cone will sufice. Calculating the position of each corner is as simple as rotating a forward vector of h length, which stars at the origin, by -0.5f*alpha degrees and +0.5f*alpha degrees respectively on the upwards direction.

A vision cone with a flat base (i.e. a triangle) can be completed by just drawing another line from corner to corner. However, for one with a curved base, a custom Gizmos shape is needed.

A custom Gizmos shape can be created by using the Gizmos.DrawLineStrip method, which requires a list of Vector3 points.

A few examples of 2D vision cones, with both flat and curved bases.
A few examples of 2D vision cones, with both flat and curved bases.

In this case, the shape needed is a circunference section, of amplitude alpha, from a circle centered at the origin with a radius of h. How many points to use for the line strip is up to us. The more points, the more “smooth” the vision cone will look. What I did is set a density of two points per unit of length and then multiply the length of the circumference section by it. Finally, I also added a baseline of 3 points to still display a curve even when the radius is too small.

int circunferenceSectionPoints = BASELINE_POINTS + POINTS_PER_UNIT_OF_DISTANCE * Mathf.RoundToInt(h * alpha * Mathf.Deg2Rad);
float angleBetweenPoints = alpha / circunferenceSectionPoints;

Getting the positions of these points can be done by modifying the vector math used earlier to get the corners: For each point i, rotate a forward vector of h length, which starts at the origin, by -0.5f*alpha + i*angleBetweenPoints git degrees on the upward direction. Add each point to a list, call the Gizmos method discussed above, and the field of view vision cone should be ready.

Gizmos or Line Renderer

I originally intended to keep this implementation as an internal tool built using Gizmos. However, during the development of the game, our team considered the possibility of displaying the vision cones to the player during gameplay. Gizmos are editor tools, which means that they are not inlcuded by default in release builds of the game.

Since I already had the math figured out, I also wrote another implementation of the logic using a LineRenderer instead of the engine’s Gizmos system, which can be exported and used on release builds of the game just like any other asset.

I tried to keep the usage consistent between both implementations, so calling the methods below with the same parameters should produce two vision cones that look the same:

GizmosVisionCones.Draw3DVisionCone(float newFieldOfView, float newDepthCone, bool newIsFlat);
aLineRendererVisionConeInstance.SetVisionConeParameters(float newFieldOfView, float newDepth, bool newIsFlat)

Another advantage of the LineRenderer implementation of this tool is that it allows for easier and further customization through exposed inspector parameters that are specific to the LineRenderer component, which artists and designers can change without dealing with code.

A side by side of the two implementations. The Gizmos vision cone is not visible during gameplay.
A side by side of the two implementations. The Gizmos vision cone is not visible during gameplay.

Download the tool

Down below is a link to the project repository. A .unitypackage asset can be found in the releases section, which includes the required scripts and a few samples to showcase its usage. Alternatively, the source code of the scripts can be copy-pasted to a Unity3D project without the samples.

Check the code in Codeberg