Build an obstacle-course world and what happens when you fall becomes a problem.
Left to the standard setting, you're returned to the spawn point. Fall after a five-minute climb and you start over. Nobody keeps playing through that.
This article builds a mechanism that returns you to the last platform you passed. It also sorts out when to use the standard mechanism instead.
What You'll Learn
- When to use standard recovery versus your own checkpoints
- Two ways to detect a fall
- What to do about falling again right after being returned
- The condition that prevents an endless respawn loop
Start from having tried building a teleporter and detecting areas with triggers.
Where standard recovery is enough, and where it isn't
VRChat ships with a mechanism for returning you after a fall: Respawn Height in the Scene Descriptor.

Fall below that height and you're returned to the spawn point. It works from a setting alone, so it's often enough on its own.
- A flat room world → standard is enough
- An exhibition or social world → standard is enough
- A world with a long route → you want to resume partway
The third is where checkpoints become necessary. Obstacle courses, escape games, exploration worlds. They prevent "after all that climbing."
What you build is a combination of two things.
- Record on passing: every time someone passes through a detection volume on a platform, remember it as "the last platform"
- Return on falling: once they drop below a set height, move them to the remembered place
Both are built from mechanisms covered in earlier articles.
Hands-On: Build a checkpoint return
Line up three platforms as a staircase and return players to the last one they passed when they fall.
1. Place the platforms and checkpoints
Place the following in a scene with a floor.
| Name | How to make it, and settings |
|---|---|
Step0 | Cube. (0, 0.5, 3), Scale (2, 0.2, 2) |
Step1 | Cube. (3, 1.5, 5), Scale (2, 0.2, 2) |
Step2 | Cube. (6, 2.5, 7), Scale (2, 0.2, 2) |

The three platforms rise gradually as they extend into the distance.
On each, place a detection volume for recording and a return position.
| Name | Parent | Settings |
|---|---|---|
Checkpoint0 | Child of Step0 | Create Empty. Local Position (0, 1, 0). Box Collider (Is Trigger on, Size (2, 2, 2)) |
Checkpoint1 | Child of Step1 | Same |
Checkpoint2 | Child of Step2 | Same |
Making them children of the platforms means the checkpoints move along when you move a platform.
2. Write the script that holds the record
First, build the side that remembers "which platform was last." Create CheckpointManager with "Create Empty" at (0, 0, 0).
Create CheckpointManager in Assets/Scripts.
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
[UdonBehaviourSyncMode(BehaviourSyncMode.None)]
public class CheckpointManager : UdonSharpBehaviour
{
[SerializeField] private Transform defaultPoint; // The first return point
[SerializeField] private float fallLimitY = -3f; // Below this counts as falling
private Transform currentPoint;
private VRCPlayerApi localPlayer;
private void Start()
{
localPlayer = Networking.LocalPlayer;
currentPoint = defaultPoint;
}
// Called from the checkpoint side
public void SetCheckpoint(Transform point)
{
if (point == null) return;
currentPoint = point;
Debug.Log("[Checkpoint] recorded: " + point.name);
}
private void Update()
{
if (!Utilities.IsValid(localPlayer)) return;
// Only compares height. Cheap work
if (localPlayer.GetPosition().y > fallLimitY) return;
Respawn();
}
private void Respawn()
{
Transform target = currentPoint != null ? currentPoint : defaultPoint;
if (target == null) return;
localPlayer.TeleportTo(target.position, target.rotation);
localPlayer.SetVelocity(Vector3.zero); // Kill the falling momentum
Debug.Log("[Checkpoint] returned to: " + target.name);
}
}
Fall detection uses Update. Running every frame may worry you, but all it does is compare one person's height, so the cost is tiny. It's more reliable than trigger-based detection, with no risk of being leapt over by a teleport.
Networking.LocalPlayer is fetched once in Start and held in a variable. That's lighter than re-fetching every frame.
3. Write the checkpoint side
Now the side that reports passage. Create CheckpointTrigger.
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
[UdonBehaviourSyncMode(BehaviourSyncMode.None)]
public class CheckpointTrigger : UdonSharpBehaviour
{
[SerializeField] private CheckpointManager manager;
[SerializeField] private Transform respawnPoint; // Return position. Empty means this object
public override void OnPlayerTriggerEnter(VRCPlayerApi player)
{
if (!player.isLocal) return; // Ignore if the person passing isn't me
if (manager == null) return;
manager.SetCheckpoint(respawnPoint != null ? respawnPoint : transform);
}
}
The isLocal check is in there. You don't want your record overwritten when someone else passes through.
Leaving respawnPoint empty returns you to the checkpoint's own position. Since it sits slightly above the platform, that works as-is.
4. Assign it and confirm
Add a Udon Behaviour to CheckpointManager, set the spawn point object as Default Point, and -3 as Fall Limit Y.
Add a Udon Behaviour to each of Checkpoint0 through Checkpoint2, set CheckpointTrigger, and drag CheckpointManager into Manager.
Press Play and try it.
| Action | Expected result |
|---|---|
Step onto Step0 | Console shows recorded: Checkpoint0 |
| Fall from there | You return above Checkpoint0 |
Climb to Step2, then fall | You return above Checkpoint2, not to the beginning |
| Right after returning | You're standing there (you don't fall again) |
The third row is the point of this mechanism. Progress moves your restart point along with you.
The return point goes above the line
One accident comes with this mechanism: an endless respawn loop.

When the return height is below the height that counts as falling (fallLimitY), this happens.
- You fall
- You're returned
- The return position is still below the line
- You're judged to have fallen again
- Repeat forever
The screen flickers and you can't move.
Preventing it is simple. Always put the return point above the line. In this example the lowest one, Checkpoint0, sits around Y=1.5 while fallLimitY is -3, which is plenty of separation.
Also, don't forget to zero the velocity right after returning. Without SetVelocity(Vector3.zero), you're returned still carrying falling momentum and cross the line again the next instant. Same endless loop.
When picking the detection height, aim for several meters below the lowest checkpoint.
Common Pitfalls
- It doesn't return you → Is
CheckpointManager's Fall Limit Y too low? Is it set to a value you never reach by falling off a platform? - The screen flickers and you can't move → An endless respawn loop. Review the return height and the detection height
- You return and fall again →
SetVelocity(Vector3.zero)is missing - Nothing gets recorded → Check that the checkpoint's Collider has Is Trigger on, and that Manager is assigned
- Someone else passing changes your record → The
isLocalcheck is missing
Bonus: Good to Know Up Front
- Keep the standard Respawn Height too: It's insurance for when this mechanism fails for some reason. Set it further below the detection height
- Each person holds their own record: This code isn't synchronized, so checkpoints are held individually. For an obstacle course, that's the correct behavior
- The return point can carry a facing too: Adjusting the checkpoint's Rotation sets which way you face on return. Facing them toward the next section is a kindness

- Signal the return: A sound or a short display makes it clear that you were returned. The sound handling in toggling with a button works here
- Checkpoints don't have to go backwards: You can build it so passing an earlier checkpoint after progressing doesn't roll the record back. Give them numbers and record only the higher one
Summary
Checkpoints are a combination of two parts.
- Record on passing (trigger +
isLocal) - Return on falling (height watch +
TeleportTo) - Kill momentum with
SetVelocity(Vector3.zero)right after returning - Always put the return point above the fall-detection line
The question to ask after building it is: "Is the return position above the line?" Miss that and you get an endless respawn loop.
To use movement mechanisms further, go to building a teleporter. To expand area detection, go to detecting areas with triggers.