【VRChat】落下復帰とチェックポイント:直前に通った足場へ戻す

作成: 2026-05-22最終更新: 2026-09-09

標準のリスポーンとの使い分けから、落ちたら直前のチェックポイントへ戻る仕掛けまで。高さの監視、速度のリセット、無限リスポーンを防ぐ書き方を解説します。

アスレチックのワールドを作ると、落ちたときの扱いが問題になります。

標準の設定に任せると、スポーン地点まで戻されます。5分かけて登った先で落ちたら、また最初からです。それでは遊ぶ気が続きません。

この記事では、落ちたら直前に通った足場へ戻る 仕掛けを作ります。標準の仕組みとの使い分けも整理します。

落ちた人が、旗の立った足場へ戻される

この記事でわかること

  • 標準の復帰と、自作のチェックポイントの使い分け
  • 落下を検知する2つの方法
  • 戻した直後にまた落ちる問題への対処
  • 無限リスポーンを防ぐ条件

テレポーターを作るトリガーでエリアを検知する を試した状態から始めます。

Sponsored


標準の復帰で足りる場面、足りない場面

VRChatには、落ちたときに戻す仕組みが最初から用意されています。Scene Descriptorの Respawn Height です。

標準の復帰は必ずスポーン地点へ、チェックポイントは直前の足場へ戻す

この高さより下に落ちると、スポーン地点へ戻されます。 設定するだけで動くので、まずはこれで十分な場面が多くあります。

  • 平らな部屋のワールド → 標準で十分
  • 展示や交流のワールド → 標準で十分
  • 長い道のりを進むワールド → 途中から再開したい

チェックポイントが必要になるのは、3つ目です。アスレチック、脱出ゲーム、探索型のワールド。「せっかくここまで来たのに」を防ぎます。

作るものは、この2つの組み合わせです。

  1. 通過したら記録する: 足場に置いた検知範囲を通るたび、そこを「直前の足場」として覚える
  2. 落ちたら戻す: 一定の高さより下がったら、覚えている場所へ移動させる

どちらも、ここまでの記事で扱った仕組みで作れます。

Sponsored

実践:チェックポイントに戻る仕掛けを作る

3つの足場を階段状に並べ、落ちたら直前に通った足場へ戻るようにします。

1. 足場とチェックポイントを置く

床のあるシーンに、次を置きます。

名前作り方と設定
Step0Cube。(0, 0.5, 3)、Scale (2, 0.2, 2)
Step1Cube。(3, 1.5, 5)、Scale (2, 0.2, 2)
Step2Cube。(6, 2.5, 7)、Scale (2, 0.2, 2)
だんだん高くなる3つの足場

3つの足場が、少しずつ高くなりながら奥へ伸びます。

それぞれの上に、記録用の検知範囲と、戻る位置を置きます。

名前設定
Checkpoint0Step0 の子Create Empty。Local Position (0, 1, 0)。Box Collider(Is Trigger オン、Size (2, 2, 2)
Checkpoint1Step1 の子同上
Checkpoint2Step2 の子同上

足場の子にしておくと、足場を動かしたときにチェックポイントも一緒に動きます。

2. 記録を持つスクリプトを書く

まず、「いまどこが直前の足場か」を覚える側を作ります。「Create Empty」で CheckpointManager を作り、(0, 0, 0) に置きます。

Assets/ScriptsCheckpointManager を作ります。

using UdonSharp;
using UnityEngine;
using VRC.SDKBase;

[UdonBehaviourSyncMode(BehaviourSyncMode.None)]
public class CheckpointManager : UdonSharpBehaviour
{
    [SerializeField] private Transform defaultPoint;   // 最初の戻り先
    [SerializeField] private float fallLimitY = -3f;   // ここより下がったら落下とみなす

    private Transform currentPoint;
    private VRCPlayerApi localPlayer;

    private void Start()
    {
        localPlayer = Networking.LocalPlayer;
        currentPoint = defaultPoint;
    }

    // チェックポイント側から呼ばれる
    public void SetCheckpoint(Transform point)
    {
        if (point == null) return;
        currentPoint = point;
        Debug.Log("[Checkpoint] 記録: " + point.name);
    }

    private void Update()
    {
        if (!Utilities.IsValid(localPlayer)) return;

        // 高さだけを見る。軽い処理
        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);   // 落ちる勢いを消す
        Debug.Log("[Checkpoint] 戻しました: " + target.name);
    }
}

落下の検知に Update を使っています。 毎フレーム動くので気になるかもしれませんが、やっているのは「自分1人の高さを比べる」だけなので、負荷はごくわずかです。トリガーで検知する方法より確実で、テレポートで飛び越えられる心配もありません。

Networking.LocalPlayerStart で1回だけ取って、変数に持っています。毎フレーム取り直すより軽くなります。

3. チェックポイント側を書く

次に、通過を知らせる側です。CheckpointTrigger を作ります。

using UdonSharp;
using UnityEngine;
using VRC.SDKBase;

[UdonBehaviourSyncMode(BehaviourSyncMode.None)]
public class CheckpointTrigger : UdonSharpBehaviour
{
    [SerializeField] private CheckpointManager manager;
    [SerializeField] private Transform respawnPoint;   // 戻る位置。空ならこのオブジェクト

    public override void OnPlayerTriggerEnter(VRCPlayerApi player)
    {
        if (!player.isLocal) return;   // 通ったのが自分でなければ無視
        if (manager == null) return;

        manager.SetCheckpoint(respawnPoint != null ? respawnPoint : transform);
    }
}

isLocal の判定が入っています。他の人が通ったときに自分の記録が書き換わっては困るからです。

respawnPoint を空にしておくと、そのチェックポイント自身の位置へ戻ります。足場の少し上に置いてあるので、そのままで使えます。

4. 割り当てて確かめる

CheckpointManager に Udon Behaviour を追加し、Default Point にスポーン地点のオブジェクトを、Fall Limit Y に -3 を設定します。

Checkpoint0 から Checkpoint2 それぞれに Udon Behaviour を追加し、CheckpointTrigger を指定して、Manager に CheckpointManager をドラッグします。

Playして試してください。

操作期待する結果
Step0 に乗るConsoleに 記録: Checkpoint0
そこから落ちるCheckpoint0 の上に戻る
Step2 まで登ってから落ちるCheckpoint2 の上に戻る。最初からやり直しにならない
戻った直後その場に立っている(また落ちない)

3行目が、この仕掛けの目的です。 進んだ分だけ、再開地点も進みます。

戻す先は、判定の線より上

この仕掛けで起きる事故が1つあります。無限リスポーン です。

チェックポイントを記録して、落ちたらそこへ戻す流れ

戻す先の高さが、落下と判定する高さ(fallLimitY)より 低い と、こうなります。

  1. 落ちる
  2. 戻される
  3. 戻った場所がまだ判定の線より下
  4. また落ちたと判定される
  5. 以下、無限に繰り返す

画面が点滅して、身動きが取れなくなります。

防ぎ方はシンプルです。戻す先は必ず判定の線より上に置きます。 今回の例では、いちばん低い Checkpoint0 がY=1.5あたりにあり、fallLimitY-3 なので、十分に離れています。

もう1つ、戻した直後に速度をゼロにする ことも忘れないでください。SetVelocity(Vector3.zero) がないと、落ちる勢いのまま戻されて、次の瞬間にまた線を割ります。結果は同じく無限リスポーンです。

判定の高さを決めるときは、いちばん低いチェックポイントより、さらに数メートル下 を目安にします。

Sponsored

うまくいかないときは

  • 戻らないCheckpointManager のFall Limit Yが低すぎないか。足場から落ちても届かない値になっていませんか
  • 点滅して動けない → 無限リスポーンです。戻す先の高さと判定の高さを見直します
  • 戻ってもまた落ちるSetVelocity(Vector3.zero) が抜けています
  • 記録されない → チェックポイントのColliderがIs Triggerか、Managerが割り当てられているかを確認します
  • 他の人が通ると自分の記録が変わるisLocal の判定が抜けています

おまけ:先に知っておくと良いこと

  • 標準のRespawn Heightも残しておく: この仕掛けが何かの理由で動かなかったときの保険になります。判定の高さより、さらに下に設定しておきます
  • 記録は各自が持つ: このコードは同期していないので、チェックポイントは1人1人が別々に持ちます。アスレチックではこれが正しい動作です
  • 戻る位置に向きも付けられる: チェックポイントのRotationを調整すると、戻ったときの正面を決められます。次に進む方向を向かせると親切です
実際に落ちて戻る様子
  • 戻ったことを知らせる: 音を鳴らしたり短い表示を出したりすると、「戻された」ことが伝わって親切です。ボタンで切り替える の音の扱いが使えます
  • チェックポイントは戻さない: 一度先に進んだあと、手前のチェックポイントを通っても記録を戻さない、という作りもできます。番号を持たせて、大きいほうだけ記録します

まとめ

チェックポイントは、2つの部品の組み合わせです。

  • 通過したら記録する(トリガー+isLocal
  • 落ちたら戻す(高さの監視+TeleportTo
  • 戻した直後に SetVelocity(Vector3.zero) で勢いを消す
  • 戻す先は、必ず落下判定の線より上に置く

作ったあとの問いかけは、「戻った場所は、判定の線より上にあるか」 です。ここを外すと無限リスポーンになります。

移動の仕組みをもっと使うなら テレポーターを作る、エリアの検知を広げるなら トリガーでエリアを検知する へ進んでください。

VRChat このセクションのノート63