Table of Contents

Custom Registerer


Before reading this page, make sure you've read System Overview to understand how prototypes, render signatures, chunks, and pools work together.

BRGRegisterer is an abstract MonoBehaviour base class for building your own instance registration components. It wraps a BRGRegistrationTracker internally, which handles the BRG singleton lifecycle, prototype reference counting, chunk tracking with automatic cleanup, overflow management, and editor support — so your subclass only needs to focus on what to register and where.

For non-MonoBehaviour usage (ECS, static managers, etc.), use BRGRegistrationTracker directly.

Both built-in registerers (BRG GameObject Group and BRG Terrain Registerer) extend this class.

For a working example, see Registerer Example.

Creating a Custom Registerer

Extend BRGRegisterer and implement two methods:

using Unity.Collections;
using Unity.Mathematics;
using UnityEngine;

namespace BRGInstancedRenderer
{
    public class MyRegisterer : BRGRegisterer
    {
        [SerializeField] GameObject _prefab;

        int _protoIndex = -1;
        ChunkLink _chunk;

        protected override void OnInitialize()
        {
            // 1. Register your render signature
            _protoIndex = RegisterRenderSignatureFromPrefab(_prefab);
            if (_protoIndex < 0) return;

            // 2. Allocate a chunk
            _chunk = AllocChunk();
            if (!_chunk.IsValid) return;

            // 3. Build instance data
            var instances = new NativeArray<InstanceData>(100, Allocator.TempJob);
            for (int i = 0; i < 100; i++)
            {
                instances[i] = new InstanceData
                {
                    position = new float3(i * 2f, 0f, 0f),
                    rotation = quaternion.identity,
                    scale = new float3(1f),
                    signatureIndex = _protoIndex,
                    color = new Color32(255, 255, 255, 255)
                };
            }

            // 4. Write to the chunk
            var bounds = new Bounds(Vector3.zero, new Vector3(200f, 10f, 10f));
            WriteChunk(_chunk, instances, bounds);
            instances.Dispose();
        }

        protected override void OnShutdown()
        {
            // Clean up local state only.
            // Do NOT free chunks or unregister render signatures - the base class does that.
            _chunk = ChunkLink.Invalid;
            _protoIndex = -1;
        }
    }
}

The base class automatically:

  • Acquires the BRGRenderer singleton
  • Calls OnInitialize() on enable, OnShutdown() on disable
  • Frees all chunks allocated via AllocChunk() on shutdown
  • Unregisters all render signatures registered via RegisterRenderSignatureFromPrefab() on shutdown
  • Handles editor lifecycle ([ExecuteAlways] with deferred initialization)

Structs

See BRGRegistrationTracker / Structs for full documentation of InstanceData, PrototypeData, RenderSignature, ChunkLink, and InstanceLink.

Properties

Property Access Type Description
BRGSystem protected BRGRenderer Reference to the singleton. Set before OnInitialize() is called, cleared after OnShutdown() returns. Use it freely during those methods.
Registration public BRGRegistrationTracker The underlying tracker. Created lazily on first access — available before Initialize().
_registered protected bool true while the registerer is initialized. Check this before performing operations.

Manual Lifecycle

By default, BRGRegisterer initializes on OnEnable and shuts down on OnDisable. If you need manual control (e.g., a button-driven workflow), override OnEnable/OnDisable and call these methods directly:

Method Description
void Initialize() Acquire the singleton and call OnInitialize(). Safe to call multiple times — does nothing if already registered.
void Shutdown() Call OnShutdown(), free all tracked chunks and prototypes, and release the singleton.

See the Registerer Example for a working example of manual lifecycle using _autoRegister.

API

These methods are forwarded to the underlying BRGRegistrationTracker. For full descriptions of each method (parameters, edge cases, etc.), see the BRGRegistrationTracker page.

Lifecycle methods (Register*, AllocChunk, WriteChunk, ReleaseChunk, AddInstance*, Get*, and the OnChunkWritten callback) are protected — intended to be used from within your subclass. Visibility controls (SetChunkEnabled, SetRenderEnabled) and the Stage* / *Unsafe modification methods are public, so other code can drive instance updates after the registerer is initialized.

Render Signature Registration

Method Description
RenderSignature ExtractRenderSignature(GameObject) Extract without registering — useful for modifying settings before registration.
int RegisterRenderSignatureFromPrefab(GameObject) Register a single signature from a prefab. Tracked.
int[] RegisterRenderSignaturesFromPrefab(GameObject) Register multiple signatures from a multi-renderer prefab. Tracked.
int RegisterRenderSignature(RenderSignature) Register an explicit signature. Tracked.
void UnregisterRenderSignature(int globalIdx) Manually unregister a prototype.

Chunk Management

Method Description
int MaxInstancesPerChunk Maximum instances per chunk (driven by Max Pool Refs Per Chunk × 16).
ChunkLink AllocChunk() Allocate a new chunk. Tracked.
void WriteChunk(ChunkLink, NativeArray<InstanceData>, Bounds, float cullDistance, float instanceCullDistance) Write instances. Auto-overflows.
void ReleaseChunk(ChunkLink) Free a chunk and all its overflows.
void RecalculateChunkBounds(ChunkLink, Bounds) Update chunk culling bounds.
void SetChunkEnabled(ChunkLink, bool) Enable/disable a chunk for rendering.
bool GetChunkEnabled(ChunkLink) Check chunk enabled state.
void SetRenderEnabled(bool) Enable/disable rendering for ALL chunks this registerer owns.

Instance Lifecycle

Method Description
InstanceLink AddInstance(ChunkLink, InstanceData) Add a single instance, with automatic overflow.
InstanceLink[] AddInstances(ChunkLink, NativeArray<InstanceData>, int count) Add multiple.
InstanceLink MoveInstanceToChunk(InstanceLink source, ChunkLink dest, InstanceData) Move between chunks.

Lookups

Method Description
InstanceLink GetInstanceLink(ChunkLink, int localIndex) Resolve a logical index (spanning primary + overflow) into a current InstanceLink.
int GetTotalChunkInstanceCount(ChunkLink) Sum across primary + overflow chunks.
int GetOverflowChunkCount(ChunkLink) Number of overflow chunks attached.
void GetPerChunkInstanceCounts(ChunkLink, List<int>) Counts per sub-chunk.

Tracked Staging

The Stage* methods buffer per-slot writes and merge updates to the same instance within a frame into a single GPU write. This is the recommended path for runtime modifications. See Tracked Staging for the full list.

Both InstanceLink and int globalSlot overloads are provided for every staging method. StageTRSBatch / StageColorBatch submit a whole NativeArray of entries in one call while keeping the per-slot merge.

Unsafe Direct Modification

The *Unsafe methods skip the staging buffer and write directly to BRGRenderer. Use only when you've already deduplicated writes yourself or need writes to land immediately. See Unsafe Direct Modification.

SetTRSBatchUnsafe / SetColorBatchUnsafe are the fastest path at scale — they bulk-stage a NativeArray (typically filled by a Burst job) straight into the core staging buffers. See Batched Unsafe Writes. For a working example of all three submission paths, see Instance Link Example.

Mixing staged and unsafe writes on the same slot within a frame is undefined — pick one path per slot.

Callbacks

Method Description
virtual void OnChunkWritten(int chunkId) Override to react when a primary chunk and all of its overflows have finished writing to GPU. Useful for caching InstanceLink handles after WriteChunk.

Notes

  • Always use RegisterRenderSignature* / AllocChunk / ReleaseChunk instead of calling BRGSystem.RegisterPrototype / BRGSystem.AllocateChunk / BRGSystem.FreeChunk directly. The base class tracks these for automatic cleanup.
  • Do not free chunks or unregister prototypes in OnShutdown(). The base class handles all BRG resource cleanup after OnShutdown() returns.
  • The BRGSystem property is set before OnInitialize() and cleared after OnShutdown(). Use it freely during those methods.
  • BRGRegisterer is marked [ExecuteAlways], so it works in the editor outside of play mode.
  • When a WriteChunk exceeds MaxInstancesPerChunk, overflow chunks are allocated automatically and share the primary chunk's bounds. All queries (GetInstanceLink, GetTotalChunkInstanceCount, etc.) span primary + overflows transparently.