Module 9 · Events and scheduling
Player and character lifecycle
Handle PlayerAdded, CharacterAdded, respawns, and players already present.
What you will learn
- Separate Player and Character lifetimes
- Handle existing players before connecting new arrivals
- Player
- The persistent session object for one connected user.
- respawn
- Creating a new Character Model for an existing Player.
Loading saved progress…
Understand
Read the idea and follow a worked example.
Why this matters
Coin Quest player state may last for the session while character-specific setup must run again after every respawn.
The mental model
A Player can receive several Character Models over one session. Connect CharacterAdded for each player and handle a current Character if one already exists.
When a script starts after players joined, iterate existing players before listening for future PlayerAdded events.
New words and symbols
--!strict asks Studio to check your code for type mistakes. It is an instruction for the editor and produces no Output message.
Matching quotes such as "hello" surround a string: a piece of text. The quotation marks tell Luau where the text starts and ends.
print(...) calls the built-in print function. Put the values to show inside its parentheses; separate multiple values with commas. Read the result in Studio's Output panel.
local is read as “local”: it creates a name that is available only in the current code scope.
if is read as “if”: it starts a decision by evaluating a condition.
then is read as “then”: it marks the body that can run when the condition is truthy.
end is read as “end”: it closes a block such as a decision, loop, or function.
for is read as “for”: it starts a controlled repetition with a changing loop value.
: is read as “colon”: it calls a method with the object supplied as the first receiver value.
A tiny example
--!strictlocal Players = game:GetService("Players")local function onCharacter(player: Player, character: Model) print(player.Name, character.Name)endlocal function onPlayer(player: Player) player.CharacterAdded:Connect(function(character) onCharacter(player, character) end) if player.Character then onCharacter(player, player.Character) endendfor _, player in Players:GetPlayers() do onPlayer(player)endPlayers.PlayerAdded:Connect(onPlayer)Line by line
- 3
Players owns session lifecycle events.
- 5
Character-specific work receives both objects.
- 9
Each player gets a future CharacterAdded listener.
- 12
An already-present Character is handled immediately.
- 17
Existing players are initialized first.
- 20
Future players use the same setup function.
Read the code aloud
Read one statement at a time: name the value being read, what the operation does, and where its result goes. Keep identifiers exactly as written so you can find them again in the code.
Pause at calls, conditions, and loops. Explain when the body runs before moving to the next statement; use the line notes above when a symbol is unfamiliar.
Execution trace
Start with the statements outside function bodies. A function definition creates a callable value; its body runs when a call, event, or scheduled task reaches it.
Trace the arguments at each call and the branch or loop inside that call. Return to the caller when the function returns. For an event, use the action named in Try it to trigger the callback.
Line 3: Players owns session lifecycle events.
Line 5: Character-specific work receives both objects.
Line 9: Each player gets a future CharacterAdded listener.
Line 12: An already-present Character is handled immediately.
Line 17: Existing players are initialized first.
Line 20: Future players use the same setup function.
State before and after
Before running, identify the starting values and any existing Studio objects this example needs. List what you expect to change.
After your practice change, check this result: Existing, future, and respawned characters each reach the same focused setup path.
Reading or printing a value leaves it unchanged. Look for assignments, calls that change state, and property updates to explain each change you observe.
Predict before running
Why check player.Character after connecting CharacterAdded?
Try it
Mark each step after you have tried it.
Common mistake
Listening only to PlayerAdded misses players who existed before the script connected. Always decide how initialization handles current state.
Checkpoint
Submit once you have considered every question. Retries are unlimited.
Recap
- Player and Character have different lifetimes.
- Existing state needs initialization.
- CharacterAdded handles future respawns.
Next: Next, you will combine touch validation, a debounce, and cleanup in a checkpoint.
Studio Companion
Not connected
Connect once. Compatible challenges will prepare automatically as you reach them.