Renvix Assets

Profiling

Unity Profiler

Vision Fog adds three markers to the CPU timeline of the Unity Profiler:

MarkerContents
VisionFog.GatherPhysics queries and reading collider outlines, main thread
VisionFog.SolveWaiting for solve jobs that are still running after the gather
VisionFog.NotifyPublishing results, rebuilding cones and the fog

The solve jobs themselves appear on the worker thread rows as VisibilityJob.

the Unity Profiler's Timeline view with the VisionFog markers on the main thread and the jobs on the worker threads.

Profile a development build connected to the Profiler for realistic numbers. See Editor and builds.

Statistics in code

VisionSystem.LastStats holds the counters and timings of the most recent update. Show them in your own debug overlay:

using Renvix.VisionFog;
using UnityEngine;

public class VisionStatsOverlay : MonoBehaviour
{
    void OnGUI()
    {
        VisionSystemStats s = VisionSystem.LastStats;
        GUILayout.Label($"Vision Fog: {s.TotalMs:F2} ms, {s.UpdatedCount}/{s.SourceCount} sources updated, {s.SkippedCount} reused");
        GUILayout.Label($"gather {s.GatherMs:F2} (physics {s.PhysicsQueryMs:F2}, checks {s.ColliderChecksMs:F2}), " +
                        $"wait {s.SolveMs:F2}, notify {s.NotifyMs:F2} ms");
    }
}
FieldDescription
SourceCountEnabled sources
UpdatedCountSources that were due for an update this frame
SkippedCountUpdated sources whose surroundings did not change, so the previous result was reused
SegmentCountObstacle edges gathered by all updated sources together
BoundaryPointCountOutline points produced by all updated sources together
GatherMsMain thread: physics queries and obstacle collection
PhysicsQueryMsPart of GatherMs: the physics overlap queries
ColliderChecksMsPart of GatherMs: the per-frame check whether each nearby collider moved or changed
ScheduleMsMain thread: starting the solve jobs
SolveMsMain thread: waiting for solves still running after the gather
NotifyMsMain thread: publishing results and rebuilding cone and fog meshes
UsedJobsTrue if the solves ran as Burst jobs
TotalMsThe sum: main-thread time of the whole vision update

VisionSystem.AfterUpdate is raised at the end of every update, a good moment to read the statistics.

What the numbers tell you

High valueLikely causeWhat to try
PhysicsQueryMsMany sources with a large Range, or many colliders on the Blocked By layersSmaller ranges, fewer layers in Blocked By, Update Every for less important sources
ColliderChecksMsVery many colliders near the sourcesMerge small colliders, use a Composite Collider 2D for tilemaps
SegmentCount per sourceDetailed colliders: mesh colliders, polygon colliders with many pointsSimpler colliders for vision, e.g. boxes on a separate layer
SolveMsNot enough worker threads, or very complex scenesFewer updated sources per frame, larger Edge Step
NotifyMsMany cones and fogs being rebuiltFewer cones, lower fog Resolution

Comparison switches

These switches exist to compare and debug. Keep their defaults in your game.

SwitchDefaultOff means
VisionSystem.UseJobstrueEverything runs on the main thread without Burst
VisionSystem.OverlapGatherAndSolvetrueAll solves start only after the whole gather
Occluders2D.CacheEnabled, Occluders3D.CacheEnabledtrueCollider outlines are read again in every update

Occluders2D and Occluders3D are in the Renvix.VisionFog.Occluders namespace.