Tutorial code often begins as a sequence of panels: show instruction, wait for input, hide instruction, mark complete. That works until the same feature must support mouse and keyboard, a gamepad, tracked controllers, gaze or direct manipulation. The sequence acquires platform checks, UI references and input subscriptions until nobody can state which part owns progress.
The underlying mistake is treating a tutorial as copy attached to controls. A production tutorial is a temporary product flow. It observes real behavior, manages progression and recovery, presents guidance in the user’s context and leaves the runtime in a valid state when it finishes or is interrupted.
1. Share product intent, not platform choreography
Start with the capability the user must understand. “Select an object,” “adjust a value,” “complete a manipulation” and “recover from an invalid state” are product intentions. A click, stick deflection or controller gesture is only one way to demonstrate them.
A shared tutorial definition can describe durable facts:
- Which capability is being introduced.
- Whether it has been completed or deliberately skipped.
- Whether the user may replay the guidance.
- Which product state makes the lesson relevant.
It should not prescribe that every platform has the same number of steps. Desktop may teach a shortcut and a pointer action. VR may require alignment, reach, controller state and a recovery path. Forcing both through one universal sequence creates branches inside every transition and produces a flow that is clear on neither platform.
2. Give durable progress one owner
Tutorial completion is persistent product data. It needs one authoritative owner that can answer whether a lesson should start, record completion and reset progress for replay. Presentation components and platform flows may observe that state, but they should not each maintain their own copy.
A small progress snapshot is usually enough: stable tutorial identifiers, completion state and the minimum versioning needed when the product changes. Keep runtime references, transient step state and device details out of persisted data.
3. Use a platform flow when the transitions differ
Shared infrastructure does not require a shared state machine. A useful composition is:
- A session decides whether onboarding is eligible and owns its lifecycle.
- A platform-specific flow owns steps, transitions and transient facts.
- A presentation snapshot describes what the user should currently see.
- A platform-specific view renders that snapshot.
- The shared progress owner records the durable result.
This separation keeps the session small. It does not need to understand head-relative placement, pointer safety or the details of a recovery sequence. The desktop and VR flows can evolve independently while still producing the same external result: a completed, skipped or interrupted tutorial.
Finite state machines are useful when entry, exit and transition rules matter. Define transitions from observable facts rather than manipulating the next panel directly. That makes replay, cancellation and failure paths part of the design instead of exceptions added later.
4. Advance from product evidence, not raw input
A tutorial should complete a step when the intended outcome happened—not merely because an input event fired. A button press may be consumed by another system. A pointer may click the wrong target. A tracked controller can report motion without producing a valid interaction.
Prefer evidence from the real consumer: selection changed, a value reached a valid range, an interaction entered the expected lifecycle state, or the product committed an operation. Input can still help identify intent, but completion should follow the behavior the user was meant to learn.
This also prevents the tutorial from fighting the product. Input subscriptions should be scoped to the active step and disposed on exit. When the tutorial updates a control that can notify listeners, use a non-notifying update or an explicit feedback guard so guidance does not trigger product actions recursively.
5. Adapt presentation to the device
Desktop guidance can rely on stable screen edges, precise pointers and familiar key glyphs. VR guidance competes with head movement, depth, occlusion, controller pose and world-space content. Reusing one visual tree for both often saves files while creating a worse experience.
Share typography, colors and semantic elements where useful, but give each platform control over layout and affordances. Input glyphs are better than raw binding text when the device is known. In VR, highlighting the relevant physical control or world-space target can remove the translation from a flat instruction to a spatial action.
Placement should be recomputed from a deliberate reference frame and stabilized against jitter. “In front of the user” is not a one-time world position: it needs a policy for height, yaw, distance, occlusion and whether it follows continuously or only when a step changes.
6. Model recovery as a first-class path
Users do not follow tutorials from a pristine state. They move early, release controls, reopen menus, change focus or enter a configuration that makes the next action impossible. A robust flow detects when its assumptions stop being true and presents a recovery action instead of continuing with stale guidance.
Recovery should answer three questions:
- Which fact is no longer valid?
- What action can restore a valid state without resetting unrelated product state?
- When is it safe to resume the main flow?
Session shutdown deserves the same attention. On completion, skip, scene change or feature teardown, remove highlights, release subscriptions, hide transient UI and stop any tutorial-owned input. A tutorial that leaves a callback or visual marker behind has not completed cleanly.
7. Validate behavior, presentation and interruption
Test each platform as its own experience while preserving a shared acceptance result. Useful checks include:
- First run, replay and already-completed behavior.
- Correct progression from the real product outcome.
- Wrong input, early input, held input and repeated input.
- Loss of focus, tracking or the active target.
- Cancellation during every step.
- UI placement, control highlighting and readability on the target device.
- No residual subscriptions, visuals or changed product state after exit.
The result is not one tutorial stretched across devices. It is one product capability taught through platform-native flows, backed by shared progress and a lifecycle the rest of the application can trust.