Forest Logo
search
package_2

tutorial

By @dontmineatnight

Roblox

Mirrored

Tutorial

A small, client-side onboarding package for Roblox experiences.

Tutorial presents guidance around UI and world targets while leaving tutorial content, input, game actions, and progression to the calling experience. It provides:

  • Spotlight guidance: a screen-space focus, tap indicator, and off-screen arrow for UI or world targets.
  • Cinematic guidance: an animated focused hole or letterbox overlay.
  • 3D guidance: optional highlights, beams, and world markers.

Tutorial does not render toast content, capture input, disable movement, or advance steps based on gameplay actions.

Installation

Add Tutorial to a Wally project:

[dependencies]
Tutorial = "dontmineatnight/tutorial@0.4.1"

Then require it from the installed package:

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Tutorial = require(ReplicatedStorage.Packages.Tutorial)

Quick start

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Tutorial = require(ReplicatedStorage.Packages.Tutorial)
local playerGui = Players.LocalPlayer:WaitForChild("PlayerGui")

local tutorial = Tutorial.new({
	steps = {
		{
			id = "open-inventory",
			title = "Open your inventory",
			description = "Select the inventory button to continue.",
			presentation = {
				screenTarget = function()
					local button = playerGui:FindFirstChild("InventoryButton", true)
					if button and button:IsA("GuiObject") then
						return button
					end
					return nil
				end,
				screenMode = "focusAndTap",
				inputHints = {
					keyboard = "Press I",
					gamepad = "Press the inventory button",
					touch = "Tap the inventory button",
				},
			},
		},
	},
	onStepChanged = function(step, _, _, target)
		-- Render step.title, step.description, and target in your own UI.
	end,
	onComplete = function()
		-- Remove the experience's instruction UI.
	end,
})

tutorial:start()

-- After the experience has confirmed the action:
-- tutorial:complete()

Use functions for targets that can be created, replaced, or moved while a step is active. Tutorial evaluates those functions during presentation updates and treats invalid or unavailable targets as absent.

Client API

Create a controller with Tutorial.new(options).

OptionDescription
stepsRequired ordered list of step inputs.
presentationA Tutorial.Presentation instance, or false to render nothing.
presentationOptionsOptions used to create the default presentation.
startStepIdOptional initial step ID.
onStepChangedReceives (step, index, count, screenTarget).
onStopRuns when an active tutorial is stopped or destroyed.
onCompleteReceives the last active step.

Controller methods:

  • start(stepId?) starts the current or named step.
  • stop() hides guidance without completing the tutorial.
  • setStep(stepId) shows a named step.
  • advance() moves to the next step, completing at the end.
  • skip() completes the tutorial locally.
  • complete() hides guidance and invokes onComplete.
  • destroy() disconnects the controller and destroys owned presentation.
  • refresh() updates dynamic targets immediately.
  • getCurrentStep() returns (step, index) while running.
  • isRunning() and isCompleted() expose controller state.
  • getPresentation() returns the presentation when one is enabled.

A presentation provides show, hide, refresh, getScreenTarget, and destroy. The screenTarget passed to onStepChanged is the target resolved when that step was shown; call getScreenTarget() after refresh() for the current target.

A controller owns the default presentation created from presentationOptions. If an existing presentation is supplied, the caller owns it; controller destruction hides it but does not destroy it.

advance, skip, and complete are local operations. For a server-authoritative tutorial, let the experience call setStep or complete only after its own server confirmation.

Step presentation

Tutorial passes title, description, and inputHints to the experience but only uses target fields for visual presentation.

presentation = {
	screenTarget = GuiObject or function() -> GuiObject?,
	screenMode = "focus" | "tap" | "focusAndTap" | "letterbox" | "none",
	worldTarget = BasePart | Model | Vector3 or function() -> target?,
	worldOrigin = BasePart | Model | Vector3 or function() -> origin?,
	worldMode = "beam" | "highlight" | "marker" | "all" | "none",
	inputHints = {
		keyboard = "...",
		gamepad = "...",
		touch = "...",
	},
}

If screenTarget is omitted and worldTarget is supplied, spotlight guidance projects the world target into screen space. It follows the target and shows an edge arrow while the target is outside the viewport.

screenMode = "letterbox" shows the screen presentation's top and bottom bars and does not require a target. The bar fraction and dim transparency are configured with ScreenGuidanceOptions.

World presentation can use a BillboardGui or Model as markerTemplate. For model markers, markerOrientation, markerDistance, and markerTargetOffset control placement and orientation. markerTargetPadding reserves space from the target when markerDistance or markerOrientation is also supplied.

Reusing visual assets

Templates are optional and are cloned by Tutorial:

local presentation = Tutorial.Presentation.new({
	screen = {
		focusTemplate = ReplicatedStorage.Assets.TutorialFocus,
		tapTemplate = ReplicatedStorage.Assets.TutorialTap,
		edgeArrowTemplate = ReplicatedStorage.Assets.TutorialArrow,
	},
	world = {
		beamTemplate = ReplicatedStorage.Assets.TutorialBeam,
		highlightTemplate = ReplicatedStorage.Assets.TutorialHighlight,
		markerTemplate = ReplicatedStorage.Assets.TutorialMarker,
	},
})

Templates provide the visual contents and structure. Tutorial owns the presentation properties needed to place, animate, and control the clones. For example, screen templates receive Tutorial's position, size, anchor, z-index, and input settings; BillboardGui markers receive Tutorial's size, offset, AlwaysOnTop, and enabled state; and Highlights receive Tutorial's adornee, depth, colors, transparencies, and enabled state. The original template instances are never modified.

Cinematic overlay

Tutorial.CinematicOverlay is a separate shared overlay for explicit cinematic transitions:

local overlay = Tutorial.CinematicOverlay

overlay.ShowLetterbox({
	barFraction = 0.12,
	transparency = 0.35,
})
overlay.Focus(targetGui, {
	scaleFactor = 1,
	transparency = 0.35,
})
overlay.Hide()
overlay.Destroy()

Focus follows a target while it remains in the local player's PlayerGui and its rendered ancestors remain visible. ShowLetterbox creates animated top and bottom bars. Both transitions use short Sine/InOut animations; their render connections and completed tweens are released automatically. Call Destroy when the experience no longer needs the shared overlay.

License

MIT

Package Details

Install command (Click to copy)


Version

0.4.3

License

MIT

check_circle

Safe for commercial use

Automated license review — not legal advice.