Game.Vehicles.ComponentsSystem
Assembly:
Namespace: Game.Vehicles
Type: class
Base: GameSystemBase
Summary:
ComponentsSystem is a Unity ECS system used in Cities: Skylines 2 to ensure newly created vehicle entities receive the appropriate transport marker components (PassengerTransport, EvacuatingTransport, PrisonerTransport) based on their "original" template entity referenced from a Temp component. It schedules a Burst-compiled IJobChunk (VehicleComponentsJob) that iterates vehicle archetype chunks, checks the original template entity for transport components using ComponentLookup.HasComponent, and enqueues AddComponent commands to a ModificationBarrier4's EntityCommandBuffer. The system uses parallel scheduling and writes to a parallel command buffer to perform component additions safely from jobs.
Fields
-
private ModificationBarrier4 m_ModificationBarrier
Used to produce an EntityCommandBuffer (as a ParallelWriter) for safely adding components from jobs and to register job dependencies via AddJobHandleForProducer. This ensures structural changes are deferred and executed on the main thread at the appropriate time. -
private EntityQuery m_VehicleQuery
Query selecting entities that are newly Created and have Vehicle and Temp components. Used with RequireForUpdate so the system only runs when relevant entities exist. -
private TypeHandle __TypeHandle
Container for the various EntityTypeHandle, ComponentTypeHandleand ComponentLookup handles used when scheduling the chunk job. Populated via the __AssignHandles method (called from OnCreateForCompiler). -
(nested)
private struct VehicleComponentsJob : IJobChunk
Burst-compiled chunk job that: - Reads the Entity and Temp arrays from the chunk.
- Uses ComponentLookup
.HasComponent on Temp.m_Original to determine whether to add transport marker components to the new vehicle entity. -
Adds components via an EntityCommandBuffer.ParallelWriter (m_CommandBuffer.AddComponent).
-
(nested)
private struct TypeHandle
Holds the EntityTypeHandle, Temp ComponentTypeHandle (read-only), and ComponentLookupinstances (read-only) required by the job. Provides __AssignHandles(ref SystemState) to request the handles from the SystemState.
Properties
- None.
Constructors
public ComponentsSystem()
Default constructor. The system is attributed with [Preserve] on lifecycle methods to avoid stripping. No custom initialization beyond base constructor.
Methods
protected override void OnCreate()
Initializes the system:- Retrieves/creates ModificationBarrier4 from the World.
- Constructs the m_VehicleQuery: entities with Created, Vehicle and Temp (all read-only).
-
Calls RequireForUpdate(m_VehicleQuery) so the system only runs when the query matches.
-
protected override void OnUpdate()
Main update that: - Prepares and schedules VehicleComponentsJob as a parallel job using JobChunkExtensions.ScheduleParallel.
- Builds job input handles via InternalCompilerInterface.GetEntityTypeHandle / GetComponentTypeHandle / GetComponentLookup using __TypeHandle fields and base.CheckedStateRef.
- Creates a parallel EntityCommandBuffer via m_ModificationBarrier.CreateCommandBuffer().AsParallelWriter().
-
Registers the scheduled JobHandle with the modification barrier via AddJobHandleForProducer and assigns the handle to base.Dependency.
-
private void __AssignQueries(ref SystemState state)
Called during compiler-time creation path (OnCreateForCompiler) — in this code it creates and immediately disposes of an EntityQueryBuilder(Allocator.Temp). This method is part of generated/compiled system scaffolding to ensure queries are set up in an ahead-of-time fashion. -
protected override void OnCreateForCompiler()
Compiler-time initialization helper that calls __AssignQueries and calls __TypeHandle.__AssignHandles(ref base.CheckedStateRef). This supports the generated Access/Handle wiring used for job scheduling. -
private struct TypeHandle.__AssignHandles(ref SystemState state)
Assigns: - EntityTypeHandle via state.GetEntityTypeHandle()
- ComponentTypeHandle
(read-only) via state.GetComponentTypeHandle (isReadOnly: true) -
ComponentLookup
(read-only) via state.GetComponentLookup (isReadOnly: true) -
private struct VehicleComponentsJob.Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
For each entity in the chunk: - Retrieves Entity and Temp arrays for the chunk.
- For each index gets the Temp.m_Original entity and checks if that original has PassengerTransport, EvacuatingTransport, or PrisonerTransport using the respective ComponentLookup.HasComponent.
- If present on original, enqueues AddComponent(unfilteredChunkIndex, e, default(TTransport)) to the parallel EntityCommandBuffer writer for the new entity.
Notes about implementation details:
- The job is marked with [BurstCompile] to enable burst optimizations.
- ComponentLookup
Usage Example
[Preserve]
protected override void OnCreate()
{
base.OnCreate();
// Create or get the modification barrier that provides an ECB for structural changes.
m_ModificationBarrier = base.World.GetOrCreateSystemManaged<ModificationBarrier4>();
// Only run this system when there are newly created vehicles with a Temp component.
m_VehicleQuery = GetEntityQuery(ComponentType.ReadOnly<Created>(),
ComponentType.ReadOnly<Vehicle>(),
ComponentType.ReadOnly<Temp>());
RequireForUpdate(m_VehicleQuery);
}
[Preserve]
protected override void OnUpdate()
{
// Scheduling the VehicleComponentsJob (simplified — actual code builds handles via internal helpers)
var job = new VehicleComponentsJob
{
m_EntityType = /* entity type handle */,
m_TempType = /* component type handle for Temp */,
m_PassengerTransportData = /* component lookup for PassengerTransport */,
m_EvacuatingTransportData = /* component lookup for EvacuatingTransport */,
m_PrisonerTransportData = /* component lookup for PrisonerTransport */,
m_CommandBuffer = m_ModificationBarrier.CreateCommandBuffer().AsParallelWriter()
};
JobHandle handle = JobChunkExtensions.ScheduleParallel(job, m_VehicleQuery, base.Dependency);
m_ModificationBarrier.AddJobHandleForProducer(handle);
base.Dependency = handle;
}
Additional remarks: - This system is part of the vehicle initialization pipeline: when vehicle entities are spawned (Created) they reference a Temp component that points back to the original prefab/template entity. ComponentsSystem inspects that template to copy marker components (by adding them to the spawned entity), enabling other systems to treat vehicles according to their transport role. - If you extend or modify transport marker types, ensure the TypeHandle and the job checks are updated accordingly. - Because this system uses ComponentLookup.HasComponent on referenced entities, the referenced originals must be accessible in the same world and not be structural-changed concurrently in a way that invalidates the lookup during job execution. The read-only ComponentLookup usage and ModificationBarrier pattern help ensure safety.