Getting Started¶
This tutorial shows you how to set up SpotlightUI and teaches you the basic implementation patterns.
Installation¶
Get the module from the GitHub repository and download the latest release.
Note
For the purposes of this tutorial, we assume the module is placed in ReplicatedStorage.SpotlightUI.
After you insert the module into your place, add a new LocalScript to StarterPlayer.StarterPlayerScripts or StarterGui and paste the following code:
-- Import the module
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local SpotlightUI = require(ReplicatedStorage.SpotlightUI)
The next part of the code defines the variables we'll use:
-- Get references to UI elements
local PlayerGui = game.Players.LocalPlayer:WaitForChild("PlayerGui")
local MyGui = PlayerGui:WaitForChild("ScreenGui")
local Button = MyGui:WaitForChild("StartButton")
local ImportantDoor = workspace:WaitForChild("TutorialDoor")
local Spotlight = SpotlightUI.new()
Note
SpotlightUI.new() is a constructor that creates a new Spotlight instance. You can reuse the same Spotlight object throughout your tutorial by calling different methods on it.
Method 1: Using Single Spotlights¶
The simplest way to use SpotlightUI is to highlight a single element:
Highlighting UI Elements¶
To spotlight a GUI element, use the FocusUI method:
This creates a spotlight around the button with 20 pixels of padding and displays the hint text "Click this button to start!"
Customizing the Spotlight¶
You can chain additional methods to customize the appearance:
Spotlight
:SetShape("Circle")
:EnablePulse(10)
:FocusUI(Button, 20, "Click this button to start!")
:Show()
Highlighting World Objects¶
To spotlight a part or model in the 3D world:
The second parameter (5) is the radius in studs around the position.
Following Moving Objects¶
If you need the spotlight to track a moving object, use FollowPart:
local MovingNPC = workspace.NPC
Spotlight
:FollowPart(MovingNPC, "Follow this character")
:EnablePulse(15)
:Show()
The spotlight will automatically update its position to track the object in real-time.
Method 2: Using Step-Based Tutorials¶
For multi-step tutorials, SpotlightUI provides a powerful step system:
local Spotlight = SpotlightUI.new()
Spotlight:SetSteps({
{
UI = MyGui.Button1,
Text = "Welcome! Click this button first",
Shape = "Circle",
Padding = 15,
Pulse = 10
},
{
Part = workspace.Checkpoint1,
Text = "Now go to this checkpoint",
Shape = "Circle"
},
{
UI = MyGui.InventoryButton,
Text = "Finally, open your inventory",
Shape = "Square",
Padding = 20
}
})
Spotlight:Start()
Each step is a table with the following optional properties:
| Property | Type | Description |
|---|---|---|
UI | GuiObject | The GUI element to spotlight |
Part | BasePart/Model | The 3D object to spotlight |
World | Vector3 | A specific position in the world |
Radius | number | Radius for world spotlights (default: 80) |
Text | string | Hint text to display |
Shape | string | "Circle" or "Square" |
Padding | number | Extra space around UI elements |
Pulse | number | Pulse animation amount (pixels) |
Warning
Each step should have either UI, Part, or World defined, but not multiple.
Advancing Through Steps¶
The tutorial automatically starts with the first step when you call :Start(). To manually advance:
Listening to Step Events¶
You can react to tutorial progress using signals:
Spotlight.stepCompleted:Connect(function(stepIndex)
print("Completed step:", stepIndex)
end)
Spotlight.sequenceCompleted:Connect(function()
print("Tutorial complete!")
end)
Interactive Tutorials¶
Here's a complete example of an interactive tutorial that advances when the player clicks buttons:
local Spotlight = SpotlightUI.new()
Spotlight:SetSteps({
{ UI = gui.PlayButton, Text = "Click to play", Shape = "Circle", Pulse = 10 },
{ UI = gui.ShopButton, Text = "Check out the shop", Shape = "Square" },
{ UI = gui.SettingsButton, Text = "Customize your settings", Shape = "Circle" }
})
gui.PlayButton.Activated:Connect(function()
if Spotlight._stepIndex == 1 then
Spotlight:Next()
end
end)
gui.ShopButton.Activated:Connect(function()
if Spotlight._stepIndex == 2 then
Spotlight:Next()
end
end)
gui.SettingsButton.Activated:Connect(function()
if Spotlight._stepIndex == 3 then
Spotlight:Next()
end
end)
Spotlight:Start()
Method 3: Hybrid Approach¶
You can combine both approaches for maximum flexibility:
local Spotlight = SpotlightUI.new()
Spotlight
:FocusUI(gui.WelcomeScreen.CloseButton, 20, "Close this to begin")
:Show()
gui.WelcomeScreen.CloseButton.Activated:Connect(function()
gui.WelcomeScreen.Visible = false
Spotlight:SetSteps({
{ Part = workspace.SpawnLocation, Text = "This is your spawn", Shape = "Circle" },
{ UI = gui.HealthBar, Text = "This is your health", Shape = "Square", Padding = 10 },
{ Part = workspace.QuestGiver, Text = "Talk to NPCs for quests", Shape = "Circle" }
})
Spotlight:Start()
end)
Cleaning Up¶
When you're done with a spotlight, always clean it up:
The Destroy() method uses Janitor internally to ensure all connections and tweens are properly cleaned up.
Best Practices¶
- One Spotlight per Tutorial - Create a new Spotlight instance for each distinct tutorial flow
- Clear Instructions - Keep hint text concise and actionable
- Appropriate Shapes - Use circles for points of interest, squares for UI elements
- Pulse Sparingly - Only use pulse on the most important steps to avoid overwhelming players
- Test on Different Screen Sizes - Ensure spotlights work well on mobile and desktop
Complete Example¶
Here's a full working example combining everything:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local SpotlightUI = require(ReplicatedStorage.SpotlightUI)
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local gui = player:WaitForChild("PlayerGui"):WaitForChild("ScreenGui")
local Tutorial = SpotlightUI.new()
Tutorial:SetSteps({
{
Part = character:WaitForChild("HumanoidRootPart"),
Text = "This is you! Use WASD to move",
Shape = "Circle",
Pulse = 15
},
{
UI = gui.Minimap,
Text = "Use the minimap to navigate",
Shape = "Square",
Padding = 10
},
{
Part = workspace.QuestBoard,
Text = "Check the quest board for missions",
Shape = "Circle"
},
{
UI = gui.InventoryButton,
Text = "Open your inventory here",
Shape = "Circle",
Padding = 20,
Pulse = 10
}
})
Tutorial.stepCompleted:Connect(function(step)
print("Player completed step:", step)
task.wait(3)
Tutorial:Next()
end)
Tutorial.sequenceCompleted:Connect(function()
print("Tutorial finished!")
player:SetAttribute("CompletedTutorial", true)
end)
Tutorial:Start()
Next Steps¶
Now that you understand the basics, explore:
- API Reference - Complete method and property documentation
- Examples - Code snippets for common use cases
- Advanced Patterns - Complex tutorial flows and edge cases