Unity Workflow LibraryUWLAbout

Topic 10 · Rendering & VFX

Pitfalls: rendering & captures

Zeroed shader globals, motion vectors, capture cameras.

Generalized pitfalls from shipped and active projects. Record your own project's traps the same way: Keeping a project pitfall file. All entries LOCKED evidence. Status: locked (empirical, seen in shipped/active projects).

  • SHADER-GLOBALS-DEFAULT-TO-ZERO — an HLSL global nobody set from C# is zero, not the value you imagined. Check: set every global at startup (or design so 0 is neutral). Status: locked (empirical, seen in shipped/active projects).
  • MANUAL-DRAWS-NEED-PREVIOUS-MATRICES — a mesh drawn by hand without a previous object-to-world matrix writes no motion vectors. Check: pass the previous matrix (RenderParams / prevObjectToWorld) for moving manual draws. Status: locked (empirical, seen in shipped/active projects).
  • INCREMENTAL-UPDATES-FOR-INSTANCED-SETS — one change must not re-upload the whole instance buffer and reset motion history. Check: dirty ranges update only changed instances. Status: locked (empirical, seen in shipped/active projects).
  • PIPELINE-SHADERS-ARE-NOT-ASMDEF-GATED — gating C# for one render pipeline with asmdef define constraints does not stop its .shader files compiling for the other pipeline. Why: Unity compiles every shader in the project for the active target. Check: pipeline-specific shaders live in a package/folder excluded from the other pipeline's projects. Status: locked (empirical, seen in shipped/active projects).
  • OVERLAY-SHADERS-MUST-BE-REFERENCED — shaders used only via Shader.Find are stripped from player builds. Check: add them to Always Included Shaders or reference a material. See also SHADER-VARIANTS-STRIP-IN-THE-PLAYER (the rendering page). Status: locked (empirical, seen in shipped/active projects).
  • ONE-QUAD-PER-CELL-FOR-TERRAIN-OVERLAYS — a terrain overlay built as one large quad per sector floats or clips over relief. Check: overlay meshes follow terrain cells (one quad per cell, sampled height). Status: locked (empirical, seen in shipped/active projects).
  • NO-CAMERA-PER-SHOT — do not create a camera + RenderTexture per screenshot. Check: reuse one capture camera and target. Status: locked (empirical, seen in shipped/active projects).
  • SCENEVIEW-IS-NOT-QA — SceneView captures are smeared by its own temporal effects and debug settings. Check: QA stills come from a game camera with production settings. Status: locked (empirical, seen in shipped/active projects).
  • WRONG-SCENE-WRONG-DIAGNOSIS — verify a look in the scene that owns it; other scenes carry their own lights and volumes. Check: name the scene and active volume profile in every look report. Status: locked (empirical, seen in shipped/active projects).
  • VOLUME-PROFILES-ARE-SELF-CONTAINED — volume profiles must embed their component sub-assets; empty/null component slots break scene/game views. Check: a validator flags null components in profiles. See also HDRP-ATMOSPHERICS-READ-AS-BUGS. Status: locked (empirical, seen in shipped/active projects).
  • CAMERA-FAR-CLIP-FITS-THE-BACKDROP — skybox/backdrop geometry must sit well inside the camera far clip. Check: backdrop radius < far clip with margin; planetary-scale cameras raise far clip and keep a sane near. Status: locked (empirical, seen in shipped/active projects).
  • DIRECTIONAL-LIGHT-CANNOT-LIGHT-A-SYSTEM-MAP — a directional light aimed at the camera lights only camera-facing sides of bodies around a central star. Check: use a point light at the star (or per-body light direction) for maps with bodies all around the source. Status: locked (empirical, seen in shipped/active projects).
  • HALF-WIRED-EFFECTS-STAY-OFF — an atmosphere/corona effect with a missing material or mesh draws as a glitched shell. Check: optional effects default off until every input is valid; validate inputs at enable. Status: locked (empirical, seen in shipped/active projects).
  • CPU-TIMING-OF-RENDER-IS-NOT-GPU-COST — Camera.Render timing measures CPU submission; GPU work runs asynchronously. Check: measure GPU time (profiler GPU module or a fence/readback). Status: locked (empirical, seen in shipped/active projects).
  • AN-EMPTY-RENDER-IS-FASTER-THAN-NOTHING — a renderer path that draws nothing measures faster than the baseline and looks like a win. Check: every perf comparison asserts visible output (pixel check or draw count) first. Status: locked (empirical, seen in shipped/active projects).
  • SETTINGS-ON-DOES-NOT-MEAN-WORKING — a pipeline feature enabled in the asset (e.g. GPU Resident Drawer) proves nothing about it being active. Check: confirm via frame debugger/stats that the feature's path is used. Status: locked (empirical, seen in shipped/active projects).