Skip to content

Game.Rendering.RequiredBatchesSystem

Assembly: Game
Namespace: Game.Rendering

Type: class

Base: GameSystemBase

Summary:
RequiredBatchesSystem is an ECS system that ensures the rendering batch groups and batch instances required by prefabs (objects, nets, lanes, zones) are created and up-to-date. It analyzes entity archetypes (Object, Composition/Orphan for nets, Lane, Block for zones) and their PrefabRef / mesh data to determine which MeshLayers, MeshTypes and LOD/partition combinations are required. It updates Prefab-related component storages (MeshData, NetCompositionMeshData, ZoneBlockData, Prefab batch-group buffers, etc.) and creates NativeBatchGroups/Batches/Instances via the BatchManagerSystem. The heavy lifting is performed inside a Burst-compiled IJobChunk (RequiredBatchesJob) that runs across relevant chunks and calls helper functions like InitializeBatchGroups / InitializeBatchGroup to create the needed groups and batches.


Fields

  • private BatchManagerSystem m_BatchManagerSystem
    {{ The BatchManagerSystem instance used to obtain native batch/group/instance buffers and to register writers for the scheduled job. Acquired in OnCreate from the World and used to create/modify native batch structures. }}

  • private EntityQuery m_UpdatedQuery
    {{ An EntityQuery selecting entities that have MeshBatch + PrefabRef and that are flagged updated (Updated or BatchesUpdated). Used to limit work to changed prefabs on normal updates. }}

  • private EntityQuery m_AllQuery
    {{ An EntityQuery selecting all MeshBatch + PrefabRef entities. Used to run a full refresh (for example once when the game finishes loading). }}

  • private bool m_Loaded
    {{ Internal flag set by OnGameLoaded to request a full pass (m_AllQuery) on the next update. GetLoaded() consumes this flag. }}

  • private TypeHandle __TypeHandle
    {{ Internal struct instance that holds ComponentTypeHandle/BufferTypeHandle/ComponentLookup/BufferLookup used to build the RequiredBatchesJob. Assigned during OnCreateForCompiler. }}

  • (nested) private struct RequiredBatchesJob
    {{ The Burst-compiled IJobChunk that iterates chunks and dispatches to UpdateObjectBatches, UpdateNetBatches, UpdateLaneBatches, UpdateZoneBatches depending on chunk types. It holds many ComponentTypeHandle/Lookup/BufferLookup references and the native batch managers and does the actual initialization of batch groups/batches/instances. }}

  • (nested) private struct TypeHandle
    {{ Helper struct that stores the ComponentTypeHandle/BufferTypeHandle/ComponentLookup/BufferLookup fields and exposes __AssignHandles(ref SystemState) to initialize them from a SystemState. }}

Properties

  • None (no public properties exposed)
    {{ This system exposes no public properties. All state is internal/private and used to schedule the RequiredBatchesJob. }}

Constructors

  • public RequiredBatchesSystem()
    {{ Default constructor. The system does most initialization in OnCreate/OnCreateForCompiler (setting up queries and type handles). }}

Methods

  • protected override void OnCreate()
    {{ Creates and caches the BatchManagerSystem and constructs the EntityQueries (m_UpdatedQuery and m_AllQuery). This is where the system prepares to perform incremental updates vs full updates. }}

  • protected override void OnGameLoaded(Context serializationContext)
    {{ Called when the game finishes loading; sets an internal flag (m_Loaded) so that the next OnUpdate uses the full query (m_AllQuery) to ensure all batch groups are created/refreshed after load. }}

  • private bool GetLoaded()
    {{ Helper that returns true once when m_Loaded is set, and clears the flag. Used to switch between incremental and full refresh behavior in OnUpdate. }}

  • protected override void OnUpdate()
    {{ Main update method. Selects which query to run (m_AllQuery if GetLoaded() is true, otherwise m_UpdatedQuery). If query is not empty, it schedules the RequiredBatchesJob (Burst compiled) using the ComponentTypeHandles and ComponentLookups from __TypeHandle and obtains native batch data from m_BatchManagerSystem. The scheduled job updates Prefab mesh metadata and creates batch groups via the BatchManager and sets base.Dependency to the created job handle. Also registers writers on the BatchManagerSystem for the job handle. }}

  • protected override void OnCreateForCompiler()
    {{ Internal initialization called by the compiled system code path. It calls __AssignQueries(ref state) and __TypeHandle.__AssignHandles(ref state) to initialize query & type handles required by job scheduling. }}

  • private void __AssignQueries(ref SystemState state)
    {{ Internal stub used to assign/prepare query builders. In this compiled form it is minimal, but is present for compiler/IL generation compatibility. }}

  • (RequiredBatchesJob) private void UpdateObjectBatches(ArchetypeChunk chunk)
    {{ Processes chunks that contain Game.Objects.Object. For each entity prefab it:

  • reads PrefabRef and prefab submeshes/submesh groups,
  • determines effective MeshLayer (Default, Moving, Marker, Tunnel, Outline) using Temp/InterpolatedTransform/Stopped/ObjectMarker/Elevation/etc.,
  • for each submesh checks MeshData.m_DefaultLayers and resolves layers/types using Net.SearchSystem.GetLayers when needed,
  • updates MeshData.m_AvailableLayers/m_AvailableTypes and calls InitializeBatchGroups for any newly required layers/types to create batch groups/batches. }}

  • (RequiredBatchesJob) private void UpdateNetBatches(ArchetypeChunk chunk)
    {{ Processes net composition entities (Composition or Orphan). Determines mesh layers (marker/outline) and for each composition entity calls UpdateNetBatches(Entity composition, MeshLayer requiredLayers) which fetches NetCompositionMeshRef / NetCompositionMeshData, computes required layers (including defaults) and updates m_AvailableLayers and calls InitializeBatchGroups to create groups/batches for nets. }}

  • (RequiredBatchesJob) private void UpdateNetBatches(Entity composition, MeshLayer requiredLayers)
    {{ Helper that checks PrefabCompositionMeshRef / NetCompositionMeshData for the given composition entity and sets up batch groups for needed layers. Takes default layers into account (if default layers are set and not a marker request) and initializes missing available layers. }}

  • (RequiredBatchesJob) private void UpdateLaneBatches(ArchetypeChunk chunk)
    {{ Processes lane entities: determines layers (outline, marker, tunnel), determines LOD limits for utility lanes, iterates prefab submeshes and resolves required layers/types similarly to objects but with lane-specific rules (MinLod, partition used when type is Lane). Calls InitializeBatchGroups for newly required layers/types and also initializes additional partitions when calculated LOD limits require it. }}

  • (RequiredBatchesJob) private void UpdateZoneBatches(ArchetypeChunk chunk)
    {{ Processes zone block entities (Block + PrefabRef). Calculates a partition index from block size and marks the zone prefab's ZoneBlockData.m_AvailableLayers/m_AvailablePartitions accordingly. Calls InitializeBatchGroups for Zone mesh types and partitions when new layers/partitions are discovered. }}

  • (RequiredBatchesJob) private void InitializeBatchGroups(Entity mesh, MeshLayer newLayers, MeshType newTypes, MeshLayer allLayers, MeshType allTypes, bool isNewPartition, ushort partition)
    {{ Iterates over bits in newLayers/newTypes and for each valid layer/type pair calls InitializeBatchGroup(mesh, layer, type, partition). If isNewPartition is true, also ensures groups for remaining (allLayers x allTypes) are created for the new partition. This coordinates which layer/type combinations to create batches for. }}

  • (RequiredBatchesJob) private void InitializeBatchGroup(Entity mesh, MeshLayer layer, MeshType type, ushort partition)
    {{ Core batch-group creation routine. Gathers mesh metadata (bounds, LOD meshes, mesh flags, submesh counts, index counts, LOD bias/shadow bias) from either MeshData, NetCompositionMeshData, or Zone helpers depending on mesh type. Computes LOD counts and per-batch properties, creates a GroupData and then calls m_NativeBatchGroups.CreateGroup to create a new batch group, adds a BatchGroup entry to the prefab's batch buffer, and creates the BatchData entries for each LOD level and base LODs (including LOD mesh entries). It also computes and clamps min-LOD and shadow LOD values per created batch. If too many batches are requested in a single group, it logs a warning. }}

  • (RequiredBatchesJob) private bool IsNetOwnerTunnel(Owner owner)
    {{ Utility that checks whether a net owner entity or any connected edges have negative elevation (tunnel). Uses m_NetElevationData lookup and m_ConnectedEdges buffer lookup to determine if any related component has min elevation < 0. If so, the lane/net should be drawn using the Tunnel layer. }}

Usage Example

[Preserve]
protected override void OnCreate()
{
    base.OnCreate();

    // Typical system setup: obtain BatchManagerSystem and build queries.
    m_BatchManagerSystem = base.World.GetOrCreateSystemManaged<BatchManagerSystem>();
    m_UpdatedQuery = GetEntityQuery(new EntityQueryDesc {
        All = new ComponentType[] {
            ComponentType.ReadOnly<MeshBatch>(),
            ComponentType.ReadOnly<PrefabRef>()
        },
        Any = new ComponentType[] {
            ComponentType.ReadOnly<Updated>(),
            ComponentType.ReadOnly<BatchesUpdated>()
        }
    });
    m_AllQuery = GetEntityQuery(ComponentType.ReadOnly<MeshBatch>(), ComponentType.ReadOnly<PrefabRef>());
}

Notes and tips for modders: - This system performs low-level rendering batch bookkeeping. If you add or modify MeshData / NetCompositionMeshData / ZoneBlockData for custom prefabs, ensure you update their default layers/types and LOD info correctly; the system will create necessary BatchGroups and Batches when it detects missing available layers/types. - The job is Burst-compiled and uses ECS lookups and native batch containers; modifying those containers concurrently without registering writers can cause race conditions. Use BatchManagerSystem.AddNativeBatch*Writer methods (as the system does) when scheduling jobs that write to native batch structures. - A full refresh of all mesh batch groups is triggered once after game load via OnGameLoaded; otherwise the system runs incrementally on changed prefabs/entities.