Build a custom render integration¶
Subclass TickRecorder to wire Tick UI into a render
pipeline that is not URP or BIRP: a custom HDRP setup, a UI
Toolkit host, or a non-Unity rendering target. This page walks
the recorder contract, what to forward, and where the existing
URP and BIRP integrations fit as references.
Most projects do not need a custom integration. The shipped URP and BIRP paths cover the common cases. Build a custom integration only when your pipeline differs fundamentally from both.
To build a custom render integration¶
-
Subclass
TickRecorder.TickRecorderis aMonoBehaviour. Override two methods:public override void RecordInto(CommandBuffer target) { m_ui.GetDrawer().RecordInto(target); } public override void SetRenderTarget(RenderTargetIdentifier target, Vector2Int size, bool isOffscreen) { m_ui.GetDrawer().SetRenderTarget(target, size, isOffscreen); }BaseGameUIis the reference subclass; copy its lifecycle if your custom host needs a similar setup. -
Choose the hook in your pipeline that records draw commands.
- URP: a
ScriptableRenderPass(seeTickRenderPass.cs). - BIRP: a
Camera-attachedCommandBufferwithOnPreRender(seeTickBIRPInjector.cs). - Pipeline-agnostic / off-screen: a direct
Graphics.ExecuteCommandBuffercall inLateUpdate(seeTickRenderTextureInjector.cs). -
HDRP or custom SRP: the equivalent injection point in your pipeline.
-
Bind your render target before
RecordIntoruns. The drawer issuestarget.DrawMeshcalls into whichever target is currently bound. The drawer itself does not bind the target; the integration does. -
Forward the active render target, its size, and the off-screen flag each frame. Call
recorder.SetRenderTarget(target, size, isOffscreen)with the target identifier, the pixel dimensions the integration is rendering into, and whether that target is off-screen (aRenderTextureor post-process intermediate) rather than the camera backbuffer. The drawer needs the target so it can restore the bound target after the frosted-glass grab-and-blit, the size so its pixel-to-NDC shader uniform matches the actual target, and the off-screen flag so it can cancel the shader Y-flip on D3D-like APIs. Without the size, the drawer falls back toScreen.*. The URP path forwards the camera target descriptor's dimensions; the BIRP path forwards the camera'spixelWidth/pixelHeight; the RenderTexture path forwards the texture's pixel size. -
Handle the frosted-glass bind-restore.
HandleDrawFrostedissues a grab-and-blit that changes the render target temporarily, then restores it. Make sure your integration's binding lifecycle survives a nested grab inside the recorded commands.
Reference implementations¶
The two shipping integrations are the canonical templates. Read the source before writing your own:
Source/Integration/URP/TickRenderPass.csandSource/Integration/URP/TickURPInjector.cs.Source/Integration/BIRP/TickBIRPInjector.cs.Source/Integration/RenderTexture/TickRenderTextureInjector.cs(the pipeline-agnostic template, closest to what a custom pipeline integration usually looks like).
All three are short. Each one is around 100 lines or fewer, and each does exactly the steps listed above.
Pitfalls¶
Frosted glass corrupts the rest of the UI.
: The integration imposes its own target binding that conflicts
with the drawer's grab-and-restore. Confirm
SetRenderTarget(target, size, isOffscreen) runs each frame so
the drawer knows which target to restore to after the blit.
Custom integration runs but nothing renders.
: The integration's hook fires, but the bound target is not the
one Tick UI is recording into. Confirm the target bound
before RecordInto runs is the one passed to
SetRenderTarget.
UI scales wrong on a non-display target.
: The integration is not forwarding the target's pixel size, so
the drawer falls back to Screen.*. Pass the actual pixel
dimensions of your target as the size argument to
SetRenderTarget(target, size, isOffscreen) each frame. Refer to
Render pipelines.
Stack-leak asserts at end of frame.
: Your DoUI is not balancing pushes and pops. The
integration is not at fault here. Refer to
Stacks.
Additional resources¶
- Render pipelines: the recorder pattern and how the drawer handles pixel coordinates.
- Drawer and batching: the command-list model the recorder consumes.
- Architecture: source-tree map.
- Render pipeline support: the matrix of supported features.