TutorialModalController extends DialogueController to create step-by-step tutorial modals with title, subtitle, image, and previous/next navigation.

Features

  • Step Navigation: Previous and next buttons with input action support
  • Title & Subtitle: Configurable header text
  • Image Support: Display images for each tutorial step
  • Return Button: Built-in escape handling and return buttons
  • Input Integration: Keyboard/gamepad navigation support

Inheritance

UIViewComponent → DialogueController → TutorialModalController

Basic Usage

csharp
using System.Collections.Generic; using UnityEngine; using CupkekGames.Luna; public class GameTutorial : MonoBehaviour { [SerializeField] private TutorialModalController _tutorial; [SerializeField] private List<TutorialStep> _steps; private int _currentStep = 0; private void Start() { _tutorial.OnNext += NextStep; _tutorial.OnPrevious += PreviousStep; ShowStep(0); } private void ShowStep(int index) { _currentStep = index; var step = _steps[index]; _tutorial.Continue( step.Description, step.Title, step.Subtitle, step.Image, skipCurrent: false ); // Disable previous on first step _tutorial.SetEnabledPrevious(index > 0); // Disable next on last step (or change to "Finish") _tutorial.SetEnabledNext(index < _steps.Count - 1); } private void NextStep() { if (_currentStep < _steps.Count - 1) { ShowStep(_currentStep + 1); } } private void PreviousStep() { if (_currentStep > 0) { ShowStep(_currentStep - 1); } } } [System.Serializable] public class TutorialStep { public string Title; public string Subtitle; public string Description; public Sprite Image; }

Methods

Continue (Extended)

Extended version with title, subtitle, and image support.

csharp
public bool Continue( string text, string title, string subtitle, Sprite image, bool skipCurrent )
ParameterDescription
textThe tutorial text (supports text effects)
titleTitle displayed at the top
subtitleSubtitle displayed below title
imageImage to display (null to hide)
skipCurrentWhether to skip currently playing text

SetTitle / SetSubtitle

Set the title and subtitle text directly.

csharp
public void SetTitle(string name) public void SetSubtitle(string name)

Image Methods

csharp
// Show image with sprite public void ShowImage(Sprite sprite) // Hide the image public void HideImage()
csharp
// Enable/disable navigation buttons public void SetEnabledNext(bool enabled) public void SetEnabledPrevious(bool enabled)

ReturnClicked

Called when return button is clicked or escape is pressed. Disables return buttons and fades out the view.

csharp
public void ReturnClicked()

Events

EventInheritedDescription
OnTextStartYesFired when text begins playing
OnTextCompleteYesFired when text finishes
OnNextNoFired when next button is pressed
OnPreviousNoFired when previous button is pressed

UXML Structure

xml
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:luna="CupkekGames.Luna"> <ui:VisualElement class="tutorial-modal"> <ui:Label name="Title" /> <ui:Label name="Subtitle" /> <ui:VisualElement name="Image" /> <ui:Label name="Speech" /> <ui:VisualElement class="navigation"> <luna:InputPrompt name="PreviousButton" /> <luna:InputPrompt name="ContinueButton" /> </ui:VisualElement> <ui:Button name="ReturnButton" text="Close" /> </ui:VisualElement> </ui:UXML>

Example: Multi-Page Tutorial

csharp
using System.Collections.Generic; using UnityEngine; using CupkekGames.Luna; public class ControlsTutorial : MonoBehaviour { [SerializeField] private TutorialModalController _tutorial; private List<TutorialPage> _pages = new() { new TutorialPage { Title = "Movement", Subtitle = "Step 1 of 4", Text = "Use <rainb>WASD</rainb> or the left stick to move your character.", Image = null // Load from resources }, new TutorialPage { Title = "Combat", Subtitle = "Step 2 of 4", Text = "Press <shake>Left Click</shake> or RT to attack enemies.", Image = null }, new TutorialPage { Title = "Inventory", Subtitle = "Step 3 of 4", Text = "Press <bounce>I</bounce> or Start to open your inventory.", Image = null }, new TutorialPage { Title = "Ready!", Subtitle = "Step 4 of 4", Text = "You're all set! Good luck on your adventure!", Image = null } }; private int _currentPage = 0; private void OnEnable() { _tutorial.OnNext += OnNext; _tutorial.OnPrevious += OnPrevious; ShowPage(0); } private void OnDisable() { _tutorial.OnNext -= OnNext; _tutorial.OnPrevious -= OnPrevious; } private void ShowPage(int index) { _currentPage = index; var page = _pages[index]; _tutorial.Continue(page.Text, page.Title, page.Subtitle, page.Image, false); // Update navigation state _tutorial.SetEnabledPrevious(index > 0); _tutorial.SetEnabledNext(index < _pages.Count - 1); } private void OnNext() { if (_currentPage < _pages.Count - 1) { ShowPage(_currentPage + 1); } else { // Tutorial complete _tutorial.ReturnClicked(); } } private void OnPrevious() { if (_currentPage > 0) { ShowPage(_currentPage - 1); } } private struct TutorialPage { public string Title; public string Subtitle; public string Text; public Sprite Image; } }

Input Actions

The tutorial uses InputPrompt for navigation buttons, which automatically display the correct input icons based on the current device.

Configure the input action names in the InputPrompt components:

  • ContinueButton - Next step action
  • PreviousButton - Previous step action

Built-in Behaviors

  • Escape Action: Automatically registered via UIViewActionEscape to close the tutorial
  • Return Buttons: All buttons named "ReturnButton" are wired to close the tutorial
  • Fade Out: Uses FadeOutThenDestroy() for smooth closing animation

Tips

  • Update the subtitle to show progress (e.g., "Step 1 of 5")
  • Disable navigation buttons at boundaries to prevent confusion
  • Use text effects to highlight important words in tutorial text
  • Images help illustrate complex concepts visually

Settings

Theme

Light

Contrast

Material

Dark

Dim

Material Dark

System

Sidebar(Light & Contrast only)

Light
Dark

Font Family

DM Sans

Wix

Inclusive Sans

AR One Sans

Direction

LTR
RTL