Advanced Topics

advanced concepts

Highlight Plus · Core Concepts

Advanced configuration topics and edge-case notes for experienced Highlight Plus users.

Quick Tips

  • Hover over any inspector label in Unity to see a built-in tooltip describing that option. Most settings do not need additional reading.
  • Effects can be previewed in Edit mode — enable Preview In Editor on the Highlight Effect.
  • If you reparent or restructure a highlighted object at runtime, call effect.Refresh() so Highlight Plus rebuilds its internal renderer cache (see Refresh After Hierarchy Change).

Normals Option

Highlight Plus can optimise mesh normals for better outline/glow rendering (applies to Fastest, Medium, and High quality modes only):

ModeEffect
SmoothImproves outline quality for Fastest and High quality levels.
Preserve OriginalForces Highlight Plus to use the original mesh without caching. Use when modifying meshes dynamically at runtime.
ReorientReplaces normals with vectors pointing outward from the object center. Useful for 2D geometry or meshes without normals.
Note: Highlight Plus never modifies your original mesh data. All normal adjustments are applied to internal copies.

Volume-Based Triggering

Automatically enable or disable highlighting when objects enter or exit a trigger volume:

  1. Add a HighlightTrigger component to the object.
  2. Set Trigger Mode to Volume.
  3. Ensure the volume has a Collider marked as Is Trigger and is set to Static.
  4. The entering object must have a Rigidbody for OnTriggerEnter / OnTriggerExit to fire.

Depth Clip

When enabled, effects are clipped by the depth buffer so they appear correctly behind solid geometry. This is important for objects that overlap or are partially embedded in surfaces.

Static Batching & MeshCollider

Objects marked Static in the Inspector get their meshes combined by Unity at scene load. Once combined, the per-object mesh is no longer accessible, so Highlight Plus cannot draw outline or glow effects for them.

Fix: attach a MeshCollider to every static GameObject you want highlighted. The MeshCollider can be disabled — its only purpose is to give Highlight Plus a reference to the original (un-batched) mesh at startup.

Note: only MeshCollider works for this. BoxCollider, SphereCollider and other primitive colliders do not expose the source mesh.

Excluding Submeshes (SubMesh Mask)

The Sub Mesh Mask property is a bitwise mask. A submesh with index i is included when (1 << i) & SubMeshMask != 0. The default value -1 means all submeshes.

GoalSub Mesh Mask value
All submeshes (default)-1
Only submesh 01  (1 << 0)
Only submesh 12  (1 << 1)
Only submesh 24  (1 << 2)
Submeshes 1 and 26  ((1 << 1) | (1 << 2))
Submeshes 0 and 39  ((1 << 0) | (1 << 3))

Custom Sorting

By default Highlight Plus sorts effects by distance to the camera. To take control of the order (e.g. force back-to-front sorting independent of camera position), set HighlightEffect.customSorting = true and resort the static HighlightEffect.effects list yourself. Full code sample in Scripting Support — Custom Sorting.

Refresh After Hierarchy Change

Highlight Plus caches the renderers and meshes of the highlighted target. If you change the hierarchy at runtime — reparenting, attaching the object to another, swapping out a child mesh — call:

effect.Refresh();              // rebuild renderer cache
effect.Refresh(discardCachedMeshes: true); // also discard cached mesh copies

Without this, the effect may render against the previous transform/mesh until the next major scene event.

Skinned Mesh Renderers

For animated characters using SkinnedMeshRenderer:

  • Enable Update When Offscreen on the SkinnedMeshRenderer to ensure bounds are updated during animations.
  • Without this, Highest Quality mode may clip effects on one side of the character because the screen-space bounding rectangle is calculated from stale renderer.bounds.

GPU-Instanced or Combined Meshes

If you use GPU instancing tools (e.g., Dynamic Mesh Combiner) that bypass standard Renderer visibility, enable Ignore Object Visibility on the HighlightEffect to force rendering.

Multiple Highlight Managers

You can use two or more Highlight Managers in the same scene, each targeting different layers. See Demo Scene 6 for a working example.

Custom Vertex Transformations

All Highlight Plus shaders share a common vertex entry point defined in HighlightPlus/Runtime/Resources/HighlightPlus/CustomVertexTransform.cginc. Edit the ComputeVertexPosition function in that file to apply project-wide vertex transforms (e.g. wind, water displacement, custom skinning) before any effect is rendered.

Heads up: changes to CustomVertexTransform.cginc are overwritten when you upgrade Highlight Plus. Keep a backup of your edits or move them to a project-level include that you re-apply after each upgrade.

Render Feature — Clear Stencil

Some third-party effects also write to the stencil buffer. If you see outline or glow randomly disappearing or being clipped after enabling another effect, open the URP Renderer Asset, locate the Highlight Plus Render Pass Feature entry and enable Clear Stencil. Highlight Plus then resets the stencil buffer at the start of its pass instead of inheriting whatever the previous feature left.

Effects Visible in SceneView but Not GameView

If effects render in the Scene tab but not in the Game tab, this is usually triggered by interactions between Depth Priming and additional render features. Two fixes:

  • Disable Depth Priming in the URP Asset (recommended — matches the default URP Setup).
  • If you cannot disable Depth Priming, set its mode to Forced so the prepass executes consistently across both views.

See-Through with Walls Only

To show the see-through effect only behind walls (not floors or ceilings):

  1. Assign walls to a dedicated layer (e.g., Walls).
  2. Set the Occlude Layer on the see-through effect to that layer.
  3. Enable the Accurate option for pixel-perfect detection.

Occlusion & Masking

There are four mechanisms that prevent or constrain Highlight Plus effects on top of other geometry. Pick the one that matches your case — they target different rendering paths.

MechanismHides effect on top of…How
Canvas UI — pipeline strategyAny UI Canvas (HUD, menus, in-world UI)Use Screen Space - Overlay, or stack a UI camera on top of the main camera.
HighlightUIMask materialSpecific Canvas UI elements (single-camera setups)Stencil-based mask material assigned to Image / RawImage / Text components.
HighlightEffectBlocker (3D)Specific 3D MeshRenderer / SkinnedMeshRenderer occludersComponent on the occluder. Cancels outline / glow / overlay on covered pixels.
HighlightSeeThroughOccluderThe see-through (X-ray) effect specificallyComponent on the occluder. Disables see-through behind it.
Add Depth To Transparent ObjectTransparent objects in front of see-through targetsEditor menu that adds a depth-write material to a transparent renderer.

Working with Canvas UI

Highlight Plus draws its passes through the URP renderer of the main camera, which means a Canvas rendered in the same pass can end up underneath the outline. There are three approaches to keep the UI on top, ordered from simplest to most flexible.

ApproachWhen to useSetup
Screen Space - Overlay Default for HUDs and most UI. Simplest and recommended option. Set the Canvas Render Mode to Screen Space - Overlay. Overlay canvases are drawn after URP finishes the frame, so they always sit on top of every Highlight Plus pass with no extra setup.
Dedicated UI camera (stacked) You need Screen Space - Camera or World Space UI (e.g. UI affected by post-processing, distortion, or attached to world geometry). Add a second Camera for the UI, set its Render Type to Overlay, and add it to the main camera’s Stack. Assign the canvas to the UI camera. Highlight Plus runs on the base camera; the UI camera draws afterwards, so the outline always stays under the UI.
HighlightUIMask material Single-camera setups where only specific UI elements should occlude the outline. See HighlightUIMask material below.

HighlightUIMask material

Assign HighlightPlus/Runtime/Resources/HighlightPlus/HighlightUIMask.mat to the Material slot of the Image, RawImage or Text component that should hide the outline. The shader writes a stencil reference but no color (ColorMask 0); the Highlight Plus outline pass tests against that stencil and skips those pixels.

Tip: HighlightUIMask makes the UI element invisible on screen because it only writes the stencil. If the UI must remain visible, duplicate the element — one copy on top with the regular UI material, one copy underneath using HighlightUIMask as the occluder.

HighlightEffectBlocker (3D Renderer Mask)

The HighlightEffectBlocker component cancels the outline, glow and overlay of a highlighted object on the pixels covered by other 3D renderers. Typical use case: a highlighted character walks behind a wall, pillar or transparent prop and you do not want its silhouette bleeding through the obstacle.

Add the component to the GameObject (or a parent of the GameObjects) whose renderers should occlude the highlight effect, and configure how it gathers renderers:

PropertyDescription
IncludeWhich renderers participate in the mask: Only This Object, Children, or Layer In Children.
Layer MaskLayer filter applied when Include is set to Layer In Children.
Object Name FilterWhen Include is Children or Layer In Children, restrict the mask to renderers whose GameObject name matches this string. Leave empty for no filtering.
Use Regular ExpressionsTreat Object Name Filter as a regex instead of a substring match.
Block Outline And GlowWhen enabled, the masked pixels suppress the outline and glow effects of any highlighted object behind them.
Block OverlayWhen enabled, the masked pixels suppress the overlay effect of any highlighted object behind them.

If you change the children, layer filter or name filter at runtime, call blocker.Refresh() on the component to rebuild its renderer list.

HighlightSeeThroughOccluder

Attach HighlightSeeThroughOccluder to a GameObject to control how it interacts with the see-through (X-ray) effect of objects behind it. The component supports two modes and two detection methods.

PropertyValuesDescription
ModeBlocksSeeThrough (default) / TriggersSeeThroughBlocksSeeThrough cancels the see-through silhouette when this object covers a highlighted target. TriggersSeeThrough activates the see-through only when this object is in front of the highlighted target.
Detection MethodStencil (default) / RayCastStencil uses a stencil mask pass — cheaper, pixel-accurate, no physics required. RayCast uses Physics raycasts against the occluder bounds — the highlighted object can query IsSeeThroughOccluded(Camera) at runtime when this method is active.

From script, you can read the occlusion state of a Highlight Effect against the registered raycast occluders:

HighlightEffect effect = GetComponent<HighlightEffect>();
bool blocked = effect.IsSeeThroughOccluded(Camera.main);
Note: IsSeeThroughOccluded(Camera) only returns meaningful values when at least one occluder is registered with BlocksSeeThrough + RayCast. Stencil mode operates entirely on the GPU and is not visible to scripts.

Add Depth To Transparent Object

The see-through effect requires occluders to write to the depth buffer. Transparent shaders typically skip depth writes, so a transparent object cannot occlude a see-through silhouette out of the box. To fix this:

  1. Select the transparent GameObject in the scene.
  2. Use the menu GameObject → Effects → Highlight Plus → Add Depth To Transparent Object. The command inserts an extra depth-only material (HighlightPlusDepthWrite.mat) at the front of the renderer’s material list.
  3. To revert: GameObject → Effects → Highlight Plus → Remove Depth Compatibility.
URP caveat: the depth-write pass has no LightMode = "DepthOnly" tag, so it only contributes when URP fills _CameraDepthTexture via Copy Depth. If your URP Renderer is configured with a Depth Prepass (or Depth Priming is forced), this workaround has no effect. Keep Depth Priming disabled, as recommended in the URP Setup, or the see-through will see straight through the transparent object regardless of this setting.
Was this page helpful?