Reference
Runtime API
Register sources, obstacles, observers, targets, concealment, modifiers, queries, and network-interest handles.
All runtime types are in KiwiStudios.FogOfWar.
FogWorld
FogWorld owns one independent fog simulation. Multiple worlds can exist without a singleton.
Sources
FogSourceSettings _settings = new FogSourceSettings(14f, 1u);
FogSourceHandle _handle = world.RegisterSource(transform, _settings);
world.UpdateSource(_handle, transform.position);
world.SetSourceActive(_handle, false);
world.UnregisterSource(_handle);Handles include an index and generation. Stale handles are rejected after a slot is reused.
For the composable vision stack, compile a FogVisionArchetype or register it directly:
FogChannelMask _team = new FogChannelMask(1ul);
FogSourceHandle _source = world.RegisterSource(transform, standardSightArchetype, _team, ownerId, visionLayer);
FogRuntimeSourceSettings _settings = standardSightArchetype.Compile(_team, ownerId, visionLayer);
world.UpdateSource(_source, transform.position, transform.forward, _settings);An archetype can contain multiple circle or cone sensors. Each sensor chooses detection channels, obstacle behavior, distance mode, visible layers, and terrain contribution. Derive from FogVisionRuleAsset to add reusable compile-time behavior without changing the solver.
Obstacles
FogObstacleHandle _handle = world.RegisterObstacle(collider, FogObstacleMode.Dynamic);
world.MarkObstacleDirty(_handle);
world.UnregisterObstacle(_handle);Programmatic bounds registration is available when no Collider is appropriate.
Use RegisterLayeredObstacle to assign one of 64 gameplay layers, or mark an obstacle as affecting all layers. Box, Sphere, and Capsule colliders retain their projected shape for entity LOS; other colliders use conservative bounds.
Observers and targets
FogObserverSettings _observerSettings = new FogObserverSettings(teamMask, ownerId, visionLayer);
FogObserverHandle _observer = world.RegisterObserver(_observerSettings);
FogTargetSettings _targetSettings = targetArchetype.Compile(enemyMask, enemyOwnerId, visionLayer);
FogTargetHandle _target = world.RegisterTarget(targetPosition, _targetSettings);
if (world.TryGetTargetVisibility(_observer, _target, out FogVisibilityDecision _decision))
{
bool _replicate = _decision.IsNetworkRelevant;
bool _showActor = _decision.Presentation != FogTargetPresentationState.Hidden;
bool _canAttack = world.EvaluateAction(_observer, _target, FogActionRequirements.Combat).IsAllowed;
}FogVisibilityDecision includes presentation, detected, targetable, network relevant, last-seen tick and time, last-known position, and FogVisibilityReason flags. FogTargetPresentationState is Hidden, LastKnown, Obscured, or Visible.
Update and unregister observers and targets with their generation-safe handles. FogVisionObserver and FogVisibilityTarget provide the equivalent component workflow.
Concealment volumes
FogVolumeHandle _brush = world.RegisterConcealmentVolume(
brushBounds,
FogConcealmentVolumeMode.OneWayBrush,
visionLayer);One-way brush blocks a source outside the volume from seeing a target inside. A source inside can see out. A sensor with brush reveal can reveal into it. Opaque blocks through-volume LOS. DetectionOnly requires its configured channels and defaults to the built-in Detection channel when no custom mask is selected; brush and opaque volumes default to Brush Reveal.
Modifiers and reveals
FogModifierHandle _sourceModifier = world.AddSourceModifier(_source, radiusBoostPreset);
FogObserverModifierHandle _observerModifier = world.AddObserverModifier(_observer, nearsightPreset);
FogRevealHandle _reveal = world.AddForcedReveal(_target, temporaryRevealPreset);
world.RemoveModifier(_sourceModifier);
world.RemoveObserverModifier(_observerModifier);
world.RemoveForcedReveal(_reveal);Preset assets produce immutable runtime settings. Durations expire in simulation time; priority resolves competing overrides. Source modifiers change radius and channels. Observer modifiers change nearsight, shared vision, or visible layers. Forced reveals can target a faction or owner and choose visible or obscured presentation.
Queries
if (world.TryGetVisibility(position, out FogVisibilityState _state))
{
bool _canRender = _state == FogVisibilityState.Visible;
}Queries are CPU-authoritative and never trigger GPU readback. Out-of-bounds queries return false.
For mode-independent current-vision checks, including MOBA mode, use:
if (world.TryIsVisible(position, out bool _isVisible))
{
bool _canRender = _isVisible;
}In MOBA mode, TryGetVisibility returns Visible or Unexplored for backward compatibility and never returns Explored. Prefer TryIsVisible when the distinction is binary.
Masks
Set FogWorld.ObserverMask for the local observer. A source contributes when (source.VisibilityMask & world.ObserverMask) != 0.
Changing the observer mask is supported at runtime. Set the new mask and call ForceRefresh when the view must switch immediately, such as a spectator changing between Team A and Team B. The MOBA Vision sample demonstrates this flow with four moving sources.
The fog query does not automatically hide gameplay objects. Use TryIsVisible to drive optional client presentation for enemy renderers, markers, health bars, and effects. Server-authoritative games must independently decide whether enemy data may be replicated or acted upon.
The competitive simulation uses FogChannelMask, which carries 128 bits. Channels 0 through 5 are reserved for Standard Sight, Detection, True Sight, Brush Reveal, Obscured Reveal, and Unobstructed. Projects can name and use the remaining channels. FogLayerMask carries 64 independent gameplay LOS layers.
Network interest
GetInterestDeltas appends reveal and hide transitions to a caller-owned list without allocating after warmup. Use a full TryGetTargetVisibility pass for late join or recovery, then apply deltas each authoritative tick. Optional NGO and Netcode for Entities samples demonstrate fail-closed transport integration.
Never populate owner identity, observer faction, target concealment, or authoritative modifiers directly from an untrusted client.
Refresh and events
ForceRefresh ignores the per-tick dirty budget and synchronously updates all caches. VisibilityUpdated fires after a fog tick. Use the event for visual adapters; avoid expensive game logic in the callback.
The entity authority simulation advances with the world tick and exposes Simulation.CurrentTick, Simulation.Stats, and detailed observer, authority-source, target, and concealment diagnostics. ShiftOrigin updates registered authority positions and last-known positions for floating-origin projects.
Textures and diagnostics
VisibilityTexture is the combined current/explored texture. CurrentVisibilityTexture and ExplorationTexture are read-only aliases for adapters that use the corresponding red or green channel. Stats, GetSourceDiagnostics, and GetObstacleDiagnostics provide allocation-free runtime diagnostics when caller-owned lists are reused.
Terrain queries and textures are a presentation contract. Entity decisions are safe for authoritative gameplay only when the simulation itself is running on the server with server-owned inputs. The package networking adapters enforce those decisions; a custom transport must do the same.
Still stuck?
Bring the world state with you.
Include the Fog of War version, Unity and URP versions, active profile and backend, relevant logs, diagnostics, and the smallest reproducible scene.