Guide
Game light beam and mirror reflection puzzle systems explained
Harbor Prism Sanctum’s third chamber looked solved: a white beam bounced off two mirrors and lit a crystal receiver. In playtests only 19% of players cleared the room on first visit. The VFX beam and the gameplay ray used different reflection normals on rotated mirrors, so the glow “almost” hit the target while the logic said miss. Designers also chained four color filters with no per-receiver tint, so players could not tell which crystal needed red versus mixed yellow. Rebuilding routing as a single authoritative ray march, adding color-matched receiver bezels, and teaching one mirror degree at a time lifted completion from 19% to 74% without reducing puzzle depth.
Light-beam puzzles route energy from emitters through mirrors, prisms, splitters, and blockers to receivers that unlock doors or power devices. They share DNA with pressure-plate logic graphs but add continuous aim: small rotation errors compound across bounces. This guide covers ray representation, mirror and prism types, color algebra, receiver coupling, performance budgets, the Harbor Prism Sanctum refactor, a technique decision table, pitfalls, and a production checklist.
Emitter–path–receiver model
Treat every puzzle as a directed graph. Emitters produce a beam with properties: origin, direction, color channel set, max bounce count, and optional intensity decay. Path nodes (mirrors, splitters, filters, portals) transform the ray at each hit. Receivers are sinks: when a beam segment endpoint lies inside a receiver volume with matching color and minimum intensity, the receiver asserts a logic signal — same pattern as plates driving AND gates.
Unlike binary switches, beams are continuous. Players reason about angles and occlusion. Your implementation must make the visible beam identical to the logic path or trust collapses instantly. One ray march function should feed both VFX line renderers and receiver tests.
2D vs 3D representation
2D tile games typically use Physics2D.Raycast or
grid DDA on integer cells. Reflection is specular in the plane: new direction
d' = d - 2(d·n)n where n is the surface
normal. Limit bounces (8–16) to prevent infinite loops in mirrored corridors.
3D first-person puzzles may use thin laser cylinders or line traces with layer masks. Rotating mirrors need the normal from the mirror transform’s forward or up axis — document which axis is reflective and keep mesh orientation aligned in the editor gizmo.
Mirror, prism, and splitter types
Fixed and rotating mirrors
Fixed mirrors are static normals — good for teach rooms. Rotating mirrors snap to 15° or 22.5° steps so solutions are enumerable; free analog rotation is harder to telegraph unless you show a degree readout. Player interaction via context prompts should rotate on press/hold with audio detents at each snap angle.
Sliding mirrors on rails change which wall you hit first; combine with rotation for advanced chambers. Serialize rail position and angle in save state.
Beam splitters and one-way glass
A 50/50 splitter continues the primary ray and spawns a secondary ray at the same hit point with reflected or refracted direction. Cap total branch depth — exponential paths blow frame budgets. One-way mirrors reflect from one side and transmit from the other; implement as hit-side tests on the collider, not double-sided reflection.
Color filters and mixers
Filters gate wavelengths: a red filter passes only the red channel. Mixers combine two inputs (red + green = yellow) at junction crystals. Use a small bitmask or RGB vector; receivers declare required color. Show filter gel color on the mesh and tint the beam after passage. Never rely on hue alone — add shape icons (circle/square/triangle) for color-blind accessibility.
Ray march algorithm (authoritative path)
Pseudocode shared by gameplay and visuals:
- Start at emitter origin with direction
d, colorc, bouncesb = 0 - Raycast along
dout to max segment length (room bounds or 50 m) - On hit: if receiver, record hit; if mirror, reflect and increment
b; if splitter, enqueue branch; if blocker, stop - Apply filter:
c ← c ∧ filterMask; ifcis zero, stop - Repeat until stop condition or
b > maxBounces
Store the polyline of hit points for the frame. VFX draws that polyline; receivers test the final segment endpoint (or any segment overlapping receiver trigger). Recompute when any mirror rotates, any slider moves, or emitter toggles — typically every frame while a mirror is being adjusted, otherwise on change events only.
Edge cases
- Grazing hits — ignore hits with dot(d, n) near zero; they flicker
- Corner seams — merge coplanar quads so rays do not snag on invisible edges
- Parallel mirrors — detect repeating bounce loops and cap with max distance
- Moving mirrors — march in fixed update or interpolate hit points for smooth beams
Receiver logic and puzzle coupling
Receivers output booleans into the same signal graph as pressure plates: AND multiple crystals to open a gate, XOR for exclusivity, delays for timed doors. A crystal should glow when energized and show a dim idle state when the wrong color arrives (brief pulse) versus no hit (dark).
For multi-step escape-room chains, treat each solved receiver as a latch that reconfigures the room: new emitter appears, blocker retracts, mirror unlocks rotation. Avoid resetting earlier crystals unless the design explicitly teaches dependency reversal.
Intensity and partial hits
Optional intensity falloff per bounce rewards efficient paths. Receivers can require minimum intensity so a beam weakened by three splitters cannot solve a far crystal. Display a brightness meter on hard receivers during playtest builds.
Feedback, teaching order, and fairness
Optical puzzles fail when players cannot see state. Minimum feedback:
- Beam color matches logic color at every segment
- Mirror snap angles visible (tick marks, holographic arc)
- Receiver bezel color matches required wavelength
- Soft “wrong color” buzz vs hard “aligned” chime
- Optional laser-dot decal where the beam terminates each frame
Teach in layers: single fixed mirror → one rotation → two mirrors → color filter → splitter → AND receiver pair. Harbor added a hallway tutorial with one rotatable mirror before Prism Sanctum; downstream completion rose 21 points before any chamber geometry changed.
Puzzle platformer fairness applies: if mis-aiming drops the player into a pit, keep mirrors away from ledges until basics are learned, or add generous checkpoints before optical rooms.
Performance and tooling
A naive splitter tree can spawn dozens of traces per frame. Mitigations:
- Recompute only dirty emitters when state changes
- Cap branches at 4–8; reject splitter placement that exceeds budget in editor validation
- Batch line meshes; avoid per-segment particle spam on mobile
- 2D: cache last polyline until mirror angle changes by ≥ 1 snap step
Editor tools: in-scene ray preview while placing mirrors, “solve hint” overlay showing target normal, heatmap of receiver hit windows across rotation steps. Designers should not ship a room without running an auto-solver that confirms at least one valid path exists.
Harbor Prism Sanctum refactor (worked example)
Baseline: Four rotatable mirrors, three color filters, three receivers (red, green, yellow) driving one AND gate. VFX used mesh normals; gameplay used collider box axes. No receiver bezels. Median time 6 min 40 s; 19% completion.
Changes:
- Unified ray march module feeding VFX and logic; one normal source per mirror
- Rotation snap 22.5° with visible detents and SFX
- Receiver crystals: idle outline color + bright fill when correctly lit
- Filter pedestals labeled with shape icons + gel color
- Upstream one-mirror tutorial room with identical snap feel
- QA overlay: ghost beam showing last frame’s failed endpoint on miss
Results: Completion 19% → 74%; median time 3 min 10 s; art-only “beam lies” bugs eliminated. Advanced players still optimize bounce order for a speedrun gate — depth preserved.
Technique decision table
| Scenario | Prefer | Avoid |
|---|---|---|
| First introduction to reflection | Single fixed mirror, one receiver | Four rotators with color mixing |
| Multi-crystal gate | AND logic + per-receiver color bezels | Identical crystals, no labels |
| Branching paths | Splitter with capped depth + visual branch tint | Unchecked exponential splits |
| Timed door after solve | Latch receiver output + decay timer | Beam must stay perfect while sprinting |
| Co-op optical room | One rotator each + shared AND | Single tiny mirror both must crowd |
| Binary on/off routing | Pressure plate or toggle mirror | Sub-degree analog aim requirement |
Pitfalls
- VFX/logic divergence — the most common optical puzzle bug; one ray march only.
- Analog rotation without feedback — players brute-force degrees; use snaps or protractors.
- Color-only encoding — inaccessible; add shapes or symbols.
- Invisible blockers — glass that stops beams but does not read as solid.
- Receiver too small — expand trigger volumes; tighten only for optional challenges.
- No solvability check — shipping an impossible mirror layout.
- Resetting entire wing on one miss — scope logic resets per output, as with plates.
Production checklist
- Single authoritative ray march drives VFX and receiver hits.
- Document reflective axis per mirror prefab; mesh matches collider.
- Cap bounces and splitter branch depth; validate in editor.
- Color filters and receivers use bitmask or vector algebra consistently.
- Add non-color cues (icons, shapes) for accessibility.
- Rotation snaps with detent audio and visible tick marks.
- Receivers show idle vs energized vs wrong-color states.
- Teach one mechanic per room before combining mirrors and filters.
- Run auto-solver or exhaustive snap search to confirm solvability.
- Serialize mirror angles, rail positions, and latched receivers on save.
- Profile beam recompute cost on target hardware; dirty-flag updates.
- Pair optical rooms with checkpoints in platformer contexts.
Key takeaways
- One ray march for visuals and logic. Divergence destroys trust.
- Optical puzzles are logic graphs with continuous aim. Reuse plate AND/OR patterns.
- Harbor Prism Sanctum rose from 19% to 74% with normals, snaps, and color bezels.
- Teach reflection before color algebra. Layer complexity deliberately.
- Cap branches and validate solvability before ship.
Related reading
- Pressure plate and switch puzzle systems — shared signal-graph patterns
- Puzzle platformer design — fairness, checkpoints, and room pacing
- Escape room design — lock hierarchies and puzzle DAGs
- Interaction systems — rotating and aiming inputs