Game.Vehicles.InitializeSystem
Assembly: Assembly-CSharp (game runtime)
Namespace: Game.Vehicles
Type: class
Base: GameSystemBase
Summary:
InitializeSystem is a Game ECS system responsible for preparing and initializing vehicle entities when they are spawned or updated. It schedules two jobs:
- TreeFixJob: reconciles moving search tree entries and lane buffers for vehicles that gained lane information.
- InitializeVehiclesJob: performs per-vehicle initialization (cars, watercraft, aircraft, parked cars and trains), including determining spawn positions/rotations, assigning lanes/parking spaces, setting up trailers/carriages, resetting mesh batches, and preparing navigation/track data.
The system also obtains a reference to the SearchSystem (moving search tree) and requires updates only when Vehicle entities are Updated.
Fields
-
private Game.Objects.SearchSystem m_SearchSystem
Holds a managed reference to the SearchSystem used for moving search tree operations (used by TreeFixJob to remove moved vehicles from the search tree). -
private EntityQuery m_VehicleQuery
EntityQuery used to select vehicle entities that the system should process. Built to require entities with Updated and Vehicle components (RequireForUpdate is called with this query). -
private TypeHandle __TypeHandle
Struct used internally to cache Entity/Component/Buffer handles and ComponentLookup/BufferLookup instances used by Burst jobs and scheduling. __TypeHandle.__AssignHandles is called to populate handles against a SystemState. -
(nested)
private struct TreeFixJob : IJobChunk
A job type scheduled from OnUpdate that ensures vehicles which now have lane information are added to lane object buffers and removed from the moving search tree. -
(nested)
private struct InitializeVehiclesJob : IJobChunk
Main job that initializes vehicle data (cars, watercraft, aircraft, parked cars, trains). Contains many helper methods (ResetMeshBatches, InitializeRoadVehicle, FindRandomConnectionLocation, UpdateBogieFrames, CalculatePathTransform, FindClosestSpawnLocation, FindParkingSpace) used during initialization. -
(nested)
private struct TypeHandle
Container of EntityTypeHandle, ComponentTypeHandle, BufferTypeHandle , ComponentLookup , BufferLookup etc. Used to set up and pass handles into Burst-compiled jobs safely.
Properties
- None (no public properties are defined on InitializeSystem).
Constructors
public InitializeSystem()
Default constructor. No special initialization; the system initialization occurs in OnCreate / OnCreateForCompiler.
Methods
protected override void OnCreate()
Called when the system is created. Responsibilities:- Calls base.OnCreate().
- Obtains or creates the Game.Objects.SearchSystem via base.World.GetOrCreateSystemManaged
() and stores it in m_SearchSystem. - Builds m_VehicleQuery to select vehicles that have been Updated and have the Vehicle component.
-
Calls RequireForUpdate(m_VehicleQuery) so the system only runs when matching entities exist.
-
protected override void OnUpdate()
Main update; prepares and schedules the two jobs described above: - Builds an InitializeVehiclesJob instance, filling it with ComponentTypeHandles, ComponentLookup, BufferLookup and a RandomSeed instance (RandomSeed.Next()) via InternalCompilerInterface.Get* calls and the cached __TypeHandle.
- Schedules InitializeVehiclesJob in parallel over m_VehicleQuery.
- Creates and schedules TreeFixJob, passing the moving search tree writer obtained from m_SearchSystem.GetMovingSearchTree(...).
- Combines dependencies appropriately and registers the resulting job handle as a moving-search-tree writer (m_SearchSystem.AddMovingSearchTreeWriter(jobHandle)).
-
Sets base.Dependency to the scheduled job handle so the ECS system dependency chain is updated.
-
protected override void OnCreateForCompiler()
Internal helper used by generated/compiled code paths: - Calls base.OnCreateForCompiler()
-
Calls __AssignQueries(ref base.CheckedStateRef) (empty in this implementation) and __TypeHandle.__AssignHandles(ref base.CheckedStateRef) to assign cached handles.
-
private void __AssignQueries(ref SystemState state)
Compiler helper that would normally build EntityQuery instances. In this file it only instantiates and immediately disposes an EntityQueryBuilder (no additional queries). -
private struct TreeFixJob.Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
TreeFixJob.Execute behavior summary: - Skips chunks containing Created component (only handles existing spawned entities).
- Iterates entities in the chunk that have CarCurrentLane and CarTrailerLane components.
-
For each vehicle with a lane component pointing to a lane that has a LaneObject buffer:
- Ensures the entity is present in the lane's LaneObject buffer (adds via NetUtils.AddLaneObject if missing).
- Removes the entity from the moving search tree (m_SearchTree.TryRemove(entity)) so it is no longer treated as a free-moving object in search structures.
-
private struct InitializeVehiclesJob.Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
Large, Burst-compiled job that performs per-vehicle initialization. High-level responsibilities: - For CarNavigation-driven chunks:
- Handle spawned/unspawned cars that have a TripSource and a PathOwner: call InitializeRoadVehicle to pick spawn location/rotation and determine lane when needed.
- If a car uses a direct target (CarNavigation.m_MaxSpeed flagged and CannotReverse), orient the vehicle to face its target and reset mesh batches.
- Initialize trailers (layout buffers) by positioning attached trailers relative to tractor, setting trailer lane if missing, and resetting their mesh batches as needed.
- Randomize m_LanePosition and set CarLaneFlags.TransformTarget if the lane Entity has a Transform component.
- Set CarNavigation.m_TargetPosition to the entity's transform position.
- For WatercraftNavigation and WatercraftCurrentLane:
- Similar to cars but with water-specific rules; sets Transform targets and flags.
- For AircraftNavigation and AircraftCurrentLane:
- Similar to cars/watercraft; handle Helicopter vs Airplane types, set ParkingSpace flag if spawn location indicates air parking space.
- For ParkedCar:
- If Unspawned and TripSource present, tries to find parking space near the TripSource with FindParkingSpace. If found, computes appropriate transform (vehicle placement) using VehicleUtils (parking lane geometry and connection lane handling).
- If not found, fallback: place at a randomized connection position (outside connections) or at TripSource transform.
- For Train chunks:
- If train has parked data or unspawned path data and layout buffer exists, initializes spawn path using PathUtils.InitializeSpawnPath and updates carriage locations using VehicleUtils.UpdateCarriageLocations; updates TrainNavigation front/rear bogie positions otherwise.
- For chunks with layout (carriages/trailers), calls UpdateBogieFrames when needed.
The job uses many helper methods (below) and accesses a wide set of ComponentLookup/BufferLookup data passed in via the TypeHandle.
- Helpers inside InitializeVehiclesJob (summaries):
-
private void ResetMeshBatches(Entity entity)
Resets MeshBatch entries (m_MeshGroup/m_MeshIndex/m_TileIndex) to default (byte.MaxValue) for the entity and recurses into sub-objects to reset their mesh batches as well. Used when a vehicle's rotation/transform changes and mesh batching must be refreshed. -
private void InitializeRoadVehicle(ref Random random, Entity vehicle, RoadTypes roadType, TripSource tripSource, PathOwner pathOwner, PrefabRef prefabRef, DynamicBuffer<PathElement> path)
Primary logic for deciding a vehicle's initial transform when it has a TripSource/path:- Attempts to use spawn locations buffer on the TripSource (if present), selecting either the closest spawn or a random spawn that matches required PathMethod/TrackTypes/RoadTypes.
- If the spawn location selection fails, tries to construct initial transform from path information via CalculatePathTransform.
- If still missing rotation, uses TripSource transform and building front position heuristics to set rotation.
- Also handles RouteLane spawn (route-specific positioning) and special cases like cargo loading and master-lane selection.
-
private Transform FindRandomConnectionLocation(ref Random random, RoadTypes roadType, Entity source, out bool positionFound, out bool rotationFound)
Chooses a random connection lane (sub-lane) from the source (or its owner/sub-lanes) that matches the requested road type and returns a Transform positioned at a representative location (e.g., at 0.5 along a curve) and a rotation oriented away from the lane tangent. Used as a fallback spawn position for outside connections. -
private void UpdateBogieFrames(DynamicBuffer<LayoutElement> layout)
Updates TrainBogieFrame buffers for carriages in the layout: each carriage that has TrainCurrentLane will have its TrainBogieFrame entries set to the front/rear bogie lanes of that carriage. -
private Transform CalculatePathTransform(Entity vehicle, PathOwner pathOwner, DynamicBuffer<PathElement> path, RoadTypes roadType, out bool positionFound, out bool rotationFound)
Walks a vehicle's path starting at pathOwner.m_ElementIndex searching for the first two transformable path targets (either entity transforms or curve positions), and from them computes a spawn position and rotation aligned with the path/tangents. Accounts for special behavior for Watercraft/Helicopter where vertical components are ignored when calculating direction. -
private Transform FindClosestSpawnLocation(ref Random random, Transform compareTransform, PathMethod pathMethods, TrackTypes trackTypes, RoadTypes roadTypes, DynamicBuffer<SpawnLocationElement> spawnLocations, bool selectRandom, out bool positionFound, out bool rotationFound)
Searches spawnLocations buffer for spawn points matching requested methods/types. If selectRandom is true, chooses a random matching spawn; otherwise finds the closest by distance. If a spawn is associated with a connected lane, uses curve position/tangent to infer rotation as well. Returns a Transform with found position and possibly rotation. -
private bool FindParkingSpace(float3 comparePosition, Entity source, ref Random random, out Entity lane, out float curvePos)
Traverses spawn location buffers, sub-lanes, building road edges and owner chain to find a parking lane near a source that supports parking. If it finds a candidate, returns lane and a curve position (clamped and randomized within a small range). Overload for searching within a DynamicBufferexists that chooses the closest parking lane. -
void IJobChunk.Execute(...)
implementations for both Job structs are present and simply forward to their typed Execute methods (standard pattern).
Usage Example
[Preserve]
protected override void OnCreate()
{
base.OnCreate();
// InitializeSystem gets SearchSystem and vehicle query here.
m_SearchSystem = base.World.GetOrCreateSystemManaged<Game.Objects.SearchSystem>();
m_VehicleQuery = GetEntityQuery(ComponentType.ReadOnly<Updated>(), ComponentType.ReadOnly<Vehicle>());
RequireForUpdate(m_VehicleQuery);
}
Additional notes and tips for modders: - InitializeSystem is Burst compiled for the job structs; any changes to the TypeHandle or job parameter lists must preserve Burst-compatible types and proper ComponentLookup/BufferLookup passing. - When adding new vehicle types or components (e.g., custom lane flags or spawn location types), ensure InitializeVehiclesJob receives the required lookups and that any new spawn/path rules are reflected in InitializeRoadVehicle and helper methods. - If interacting with the moving search tree (m_SearchSystem), be careful to register writers using m_SearchSystem.AddMovingSearchTreeWriter(jobHandle) as done here to avoid race conditions. - Many utility functions are used (VehicleUtils, PathUtils, MathUtils, NetUtils). Reuse them where possible for consistent behavior with built-in vehicle placement and routing.