Game.StreetLightSystem
Assembly: Game (Game.dll)
Namespace: Game.Simulation
Type: class
Base: GameSystemBase
Summary:
Manages the on/off state of street light objects for roads, buildings and watercraft. Runs a Burst-compiled IJobChunk (UpdateStreetLightsJob) on a scheduled interval to:
- Check whether roads, buildings and watercraft should have their lights on based on time-of-day brightness and random seed.
- Check electricity connectivity through electricity node connections and flow edges.
- Flip entity flags (RoadFlags.LightsOff, BuildingFlags.StreetLightsOff, WatercraftFlags.LightsOff / Illuminated) as appropriate.
- Update associated StreetLight component data for sub-objects and enqueue EffectsUpdated / BatchesUpdated via an EndFrameBarrier command buffer so rendering/effects are refreshed.
This system is optimized for parallel execution using Unity ECS job chunking, ComponentLookup/BufferLookup, and Burst. It queries all entities that have UpdateFrame and either Road, Building or Watercraft components, excluding Deleted/Destroyed/Temp.
Fields
-
private const uint UPDATE_INTERVAL = 256u
{{ Internal constant used when computing update frames (not used directly in GetUpdateInterval override). }} -
private SimulationSystem m_SimulationSystem
{{ Reference to the global SimulationSystem used to obtain the current frame index / simulation timing. }} -
private LightingSystem m_LightingSystem
{{ Reference to the LightingSystem used to obtain current day/night brightness (m_LightingSystem.dayLightBrightness). }} -
private EndFrameBarrier m_EndFrameBarrier
{{ Reference to the EndFrameBarrier system — used to create a parallel command buffer (EntityCommandBuffer.ParallelWriter) so entity/component changes are recorded safely from jobs and applied at the end of the frame. }} -
private EntityQuery m_StreetLightQuery
{{ EntityQuery that selects entities with UpdateFrame and any of Road, Building or Watercraft, while excluding Deleted, Destroyed and Temp. Used to schedule the UpdateStreetLightsJob. }} -
private TypeHandle __TypeHandle
{{ Internal structure storing component/buffer type handles and lookups used for job scheduling. }} -
private struct UpdateStreetLightsJob
(nested)
{{ Burst-compiled IJobChunk that performs the bulk of the work per-chunk: reads Road/Building/Watercraft, PseudoRandomSeed, electricity connections, subobjects and streetlight component data; computes whether lights should be on or off; updates component flags and enqueues EffectsUpdated/BatchesUpdated through an EntityCommandBuffer.ParallelWriter. Uses ComponentLookup and BufferLookup for safe parallel access. }} -
private struct TypeHandle
(nested)
{{ Holds pre-resolved EntityTypeHandle, ComponentTypeHandle, BufferTypeHandle and ComponentLookup/BufferLookup instances and a helper to assign them from a SystemState. }}
Properties
- (none public)
{{ The system exposes no modifiable public properties. Internal TypeHandle and query/state are private. }}
Constructors
public StreetLightSystem()
{{ Default constructor — standard system instantiation. System setup primarily happens in OnCreate/OnCreateForCompiler. Marked with [Preserve] on lifecycle methods to avoid stripping. }}
Methods
-
public override int GetUpdateInterval(SystemUpdatePhase phase)
{{ Returns the interval used by the system's UpdateFrame logic. In this implementation it always returns 16, meaning the system selects the UpdateFrame based on a 16-frame interval when scheduling. This interacts with the UpdateFrame shared component filter in OnUpdate. }} -
[Preserve] protected override void OnCreate()
{{ System initialization: - Resolves SimulationSystem, LightingSystem and EndFrameBarrier from the World.
- Builds the EntityQuery (m_StreetLightQuery) that matches UpdateFrame and any of Road/Building/Watercraft and excludes Deleted/Destroyed/Temp.
- Calls RequireForUpdate(m_StreetLightQuery) so the system only runs when matching entities exist.
-
Contains asserts (no-op checks here). This is where system-level references and the query are created; no heavy work is done here. }}
-
[Preserve] protected override void OnUpdate()
{{ Main scheduling function: - Resets filters on m_StreetLightQuery and sets a shared component filter UpdateFrame computed from m_SimulationSystem.frameIndex and GetUpdateInterval (16).
- Prepares an UpdateStreetLightsJob instance:
- Assigns entity/component/buffer handles through InternalCompilerInterface.Get... helpers (wired to __TypeHandle).
- Computes m_Brightness = Mathf.RoundToInt(m_LightingSystem.dayLightBrightness * 1000f).
- Creates a parallel command buffer from m_EndFrameBarrier.
- Schedules the job in parallel using JobChunkExtensions.ScheduleParallel with the query and current Dependency.
- Adds the returned JobHandle to the EndFrameBarrier (AddJobHandleForProducer) so the barrier knows to wait for / play back commands after the job finishes.
-
Stores the job handle on base.Dependency. }}
-
public static void UpdateStreetLightState(ref StreetLight streetLight, Road road)
{{ Static helper to update a StreetLight component based on a Road's flags. If road has RoadFlags.LightsOff set, sets StreetLightState.TurnedOff on the component; otherwise clears that flag. Intended to be used when a road's light state changes to update associated sub-object StreetLight components. }} -
public static void UpdateStreetLightState(ref StreetLight streetLight, Building building)
{{ Same as above but for Building: toggles StreetLightState.TurnedOff depending on BuildingFlags.StreetLightsOff. }} -
public static void UpdateStreetLightState(ref StreetLight streetLight, Watercraft watercraft)
{{ Same as above but for Watercraft: toggles StreetLightState.TurnedOff depending on WatercraftFlags.LightsOff / DeckLights. }} -
protected override void OnCreateForCompiler()
{{ Internal helper used by generated code paths: assigns queries and type handles from the SystemState to prepare for job scheduling. }} -
private void __AssignQueries(ref SystemState state)
{{ Internal placeholder used by compiler-generated code to prepare query builders / validations. }} -
Note on UpdateStreetLightsJob internal methods:
- Execute(in ArchetypeChunk, int, bool, in v128): iterates chunk entities and for each Road/Building/Watercraft:
- Uses PseudoRandomSeed to add randomness to brightness checks.
- Checks electricity connectivity:
- For roads/buildings: uses ElectricityNodeConnection and ConnectedFlowEdge/ElectricityFlowEdge lookups to detect disconnected nodes.
- For buildings: may consult ElectricityConsumer component if present.
- Compares m_Brightness against a randomized threshold (random.NextInt(200,300)) to decide if lights should be on.
- Toggles entity flags and updates sub-objects' StreetLight components via ComponentLookup
and writes EffectsUpdated/BatchesUpdated using m_CommandBuffer.AddComponent.
- The job uses NativeArray, BufferAccessor, ComponentLookup and BufferLookup for high-performance parallel reads and writes, and uses an EntityCommandBuffer.ParallelWriter for structural/side-effect changes. The job is Burst-compiled for speed. }}
Usage Example
// Example: force-update a subobject StreetLight component from your own system.
// You might call this if you want to manually set a light state for a subobject.
void SetSubObjectStreetLight(EntityManager em, Entity subObject, bool turnOff)
{
if (em.HasComponent<StreetLight>(subObject))
{
var streetLight = em.GetComponentData<StreetLight>(subObject);
if (turnOff)
streetLight.m_State |= StreetLightState.TurnedOff;
else
streetLight.m_State &= ~StreetLightState.TurnedOff;
em.SetComponentData(subObject, streetLight);
// Make sure effects/rendering are updated
em.AddComponent<EffectsUpdated>(subObject);
}
}
Additional notes for modders: - The system relies on m_LightingSystem.dayLightBrightness to determine global brightness; brightness is multiplied by 1000 and compared against random thresholds in [200,300). - Electricity connectivity checks traverse electricity node connections and connected flow edges: if any connected ElectricityFlowEdge has isDisconnected, the node is considered disconnected and lights will not turn on. - The system schedules work on background threads (Burst/IJobChunk). Do not access UnityEngine.Object or main-thread-only APIs from within UpdateStreetLightsJob. - To observe or modify behavior, either: - Replace/extend this system by creating a new system that runs earlier/later and changes relevant flags/components, or - Intercept / modify StreetLight components or Road/Building/Watercraft flags and ensure EffectsUpdated / BatchesUpdated are added when needed so rendering updates. - Because changes are applied via EndFrameBarrier command buffer, component adds/structural changes are deferred until job completion and playback at frame end.