Skip to content

Configure RenderTexture for Tick UI

Render Tick UI into a RenderTexture and sample the texture from a material to display the UI on an in-world surface, such as a quad, a screen mesh, or a curved holopanel. This path suits diegetic HUDs, in-game monitors, and VR worldspace UI.

This page assumes you have already installed Tick UI and read Set up Tick UI.

To configure the RenderTexture path

  1. Create or assign a RenderTexture asset. Pick the pixel dimensions you want the UI to render at; the drawer's pixel-to-NDC conversion uses the texture's size, so sub-screen sizes work fine.
  2. Create a GameObject for the UI recorder. Attach your BaseGameUI subclass (the one with the DoUI override) to it. The RenderTexture path does not require the recorder to live on the same GameObject as the injector, so put it wherever fits your scene structure.
  3. Create a GameObject for the injector. Attach TickRenderTextureInjector. In the Inspector:
  4. Recorder: drag in the BaseGameUI you just placed. This injector takes the recorder as an explicit field.
  5. Render Texture: drag in the texture from step 1.
  6. Clear Each Frame: leave on for transparent UI; turn off if upstream code already writes to the texture and you want Tick UI to composite over the existing contents.
  7. Clear Color: defaults to fully transparent. Change only if the UI is meant to occupy the whole texture and a solid background is wanted.
  8. Display the texture in the scene. Create a quad (or any mesh), assign a material that samples the RenderTexture, and place it in the world. The material's shader should respect the texture's alpha if you want the transparent areas to show what's behind the surface.
  9. Press play. The injector executes its CommandBuffer each LateUpdate after the recorder's DoUI runs, so the texture refreshes every frame.

Pipeline-agnostic by design

TickRenderTextureInjector does not hook into the camera. It runs Graphics.ExecuteCommandBuffer directly each frame, so the path works on URP, BIRP, HDRP, and any custom SRP. The recorder's draw output never touches the active pipeline's camera graph.

The component sets [DefaultExecutionOrder(100)], so it runs after most user code in LateUpdate. That ordering matters: the recorder's DoUI runs in its own LateUpdate (driven by BaseGameUI), and the injector then records the resulting draws into the texture. Keep your gameplay code's execution order at the default unless you have a specific reason to change it.

When to use the RenderTexture path

Use the RenderTexture path when:

  • The UI lives in the world, such as a screen, a panel, or a holographic display.
  • You want pipeline-agnostic code, for example a package that targets multiple pipelines.
  • You want the UI to render to a texture for reading back, recording, or post-processing as an asset.
  • You want multiple UIs in one scene at different qualities or sizes.

Use the camera-driven URP or BIRP path when:

  • The UI is a HUD or full-screen overlay.
  • The project is committed to a single pipeline.
  • The UI is the final visual output of the camera.
  • One UI per camera is enough.

The three paths can coexist. A common pattern: a BaseGameUI subclass for the screen-space HUD attached to the camera with TickBIRPInjector or TickURPInjector, plus a separate BaseGameUI for an in-world interactive panel attached to a different GameObject and driven by TickRenderTextureInjector.

Pitfalls

The texture is black. : Either the Render Texture field is unassigned, the Recorder field is unassigned, or the recorder's DoUI is not drawing anything. Check both Inspector fields and confirm DoUI runs (a Debug.Log at the top of DoUI confirms this).

The UI shows but the world behind it is black. : Clear Each Frame is on with an opaque clear colour, or the material sampling the texture does not respect alpha. Set Clear Color alpha to 0, and use a transparent shader on the surface displaying the texture.

The UI lags behind in-world objects by one frame. : The injector runs in LateUpdate at execution order 100, after most game code. If your in-world UI follows an object that itself moves in LateUpdate, ensure the moving object runs first (lower execution-order value or earlier LateUpdate). The texture is sampled at render time, so the visible state matches the frame's final transforms.

UI scales wrong on the surface. : The injector forwards the texture's pixel dimensions to the drawer each frame, so the layout is correct relative to the texture. If the surface displaying the texture is stretched in world space, the UI stretches with it. That is a material and mesh concern, not a UI one. Use a uniform-scale quad sized in the texture's aspect ratio.

Additional resources