【VRChat】プレイヤーイベント:参加と退出を受け取って人数を表示する

作成: 2025-12-19最終更新: 2026-09-09

OnPlayerJoinedとOnPlayerLeftで人数を数え、壁の掲示板に表示します。「誰のクライアントで、誰について呼ばれるか」を整理し、入室時に既にいた人の分も呼ばれる仕組みを解説します。

ワールドに何人いるか、壁に表示したい。誰かが入ってきたら歓迎の音を鳴らしたい。

VRChatには、参加と退出を受け取るイベントがあります。ただし「誰のクライアントで、誰について呼ばれるのか」が分かっていないと、人数が合わなくなります。

この記事では、参加と退出を受け取って、壁の掲示板に「いま3人」と表示する ところまでを作ります。

壁の掲示板に人数が表示され、部屋に3人いる

この記事でわかること

  • 誰のクライアントで、誰について呼ばれるか
  • 入室時に、先にいた人の分も呼ばれること
  • 人数の正しい数え方
  • UdonからTextMeshProに文字を出す方法

変数と参照 を試した状態から始めます。

Sponsored


誰のPCで、誰について呼ばれるか

プレイヤーイベントは、この2つを分けて考えると混乱しません。

誰が入ってきたかが、全員のクライアントで通知される

OnPlayerJoined(VRCPlayerApi player) は、インスタンスにいる全員のPCで 呼ばれます。引数の player が「入ってきた人」です。

  • Aさんが入る → その場にいるBさん・Cさんのクライアントで OnPlayerJoined(A) が呼ばれる
  • 同時に、Aさん自身のクライアントでも OnPlayerJoined(A) が呼ばれる

ここまではイメージどおりだと思います。大事なのは次です。

自分が入ったとき、既にいた人の分も呼ばれます。

Aさんが入った時点でBさんとCさんがいたなら、Aさんのクライアントでは OnPlayerJoined(A) OnPlayerJoined(B) OnPlayerJoined(C) が順に実行されます。その場にいる全員分 です。

この仕組みのおかげで、あとから入った人でも「いま誰がいるか」を自分で把握できます。もしこれがなければ、入室後に来た人しか分からず、人数がずれます。

退出も同じです。OnPlayerLeft(VRCPlayerApi player) が、残っている全員のPCで呼ばれます。

同期は使っていません。 各自のPCが、自分で数えて自分の画面を書き換えます。それでも全員が同じ数になります。

Sponsored

実践:人数を掲示板に表示する

壁の掲示板に、いまワールドにいる人数を表示します。誰かが出入りするたびに更新されます。

人が入ってくると、掲示板の人数が増える

1. 掲示板を作る

文字を表示するには、World Space の Canvas が必要です。ワールドの中に浮かぶ看板だと思ってください。

  1. Hierarchyで「UI → Canvas」を作り、InfoCanvas と名付ける
  2. CanvasのRender Modeを World Space にする
  3. Rect Transformを Position (0, 2, 2.8)、Width 400、Height 200、Scale を (0.005, 0.005, 0.005) にする
  4. InfoCanvas を右クリックして「UI → Text - TextMeshPro」を追加し、CountText と名付ける

Canvasの Scale を小さくしているのは、UIの1単位がそのままメートルになってしまうためです。0.005にすると、幅400のCanvasが2mの看板になります。

CountText の Font Size を 72 くらいにして、Alignment を中央にします。

2. コードを書く

Assets/Scripts で「Create → U# Script」を選び、PlayerCounter を作ります。

using UdonSharp;
using UnityEngine;
using TMPro;
using VRC.SDKBase;

[UdonBehaviourSyncMode(BehaviourSyncMode.None)]
public class PlayerCounter : UdonSharpBehaviour
{
    [SerializeField] private TextMeshProUGUI countText;

    private void Start()
    {
        UpdateDisplay();
    }

    // 誰かが入ってきたとき(自分が入ったときも呼ばれる)
    public override void OnPlayerJoined(VRCPlayerApi player)
    {
        UpdateDisplay();
        Debug.Log("[PlayerCounter] 参加:" + player.displayName);
    }

    // 誰かが出ていったとき
    public override void OnPlayerLeft(VRCPlayerApi player)
    {
        UpdateDisplay();
        Debug.Log("[PlayerCounter] 退出:" + player.displayName);
    }

    // 人数を数え直して、表示に反映する
    private void UpdateDisplay()
    {
        if (countText == null) return;

        int count = VRCPlayerApi.GetPlayerCount();
        countText.text = "いま " + count + " 人";
    }
}

短いです。ポイントは UpdateDisplay() の中身にあります。

変数で人数を足し引きしていません。 イベントが来るたびに GetPlayerCount() で数え直しています。この理由は次の節で説明します。

3. 割り当てて確かめる

InfoCanvas に Udon Behaviour を追加し、PlayerCounter を指定します。Count Text に CountText をドラッグします。

ClientSimでPlayすると、「いま 1 人」と出ます。自分1人だからです。

本番の確認はBuild & Testで行います。 Number of Clients を 2 にしてビルドしてください。

操作期待する結果
1人目が入る「いま 1 人」
2人目が入る両方の画面で「いま 2 人」
2人目が出る残った画面で「いま 1 人」

両方の画面で同じ数字が出ること を確かめてください。同期のコードは1行も書いていないのに、そろっています。各自が自分で数えているからです。

数えるのではなく、取り直す

人数の数え方には2つの流儀があります。

自分で数えるとずれる。取り直せば合う

イベントで足し引きする方法 はこうです。

private int count;

public override void OnPlayerJoined(VRCPlayerApi player)
{
    count++;   // 増やす
}

public override void OnPlayerLeft(VRCPlayerApi player)
{
    count--;   // 減らす
}

一見よさそうですが、一度ずれると戻りません。 何かの理由でイベントを取りこぼしたり、初期値がずれたりすると、実際の人数と食い違ったまま動き続けます。

毎回取り直す方法 なら、その心配がありません。

int count = VRCPlayerApi.GetPlayerCount();

GetPlayerCount() は、呼んだ時点の実際の人数を返します。イベントは「いま人数が変わった」というきっかけとして使い、数そのものは毎回聞き直す。これが安全な作り方です。

同じ考え方は、他の場面でも効きます。「自分で数えて覚えておく」より、「必要なときに実際の値を取る」ほうが、ずれる余地がありません。

うまくいかないときは

  • 文字が表示されない → Count Textが None になっていないか。CanvasのRender ModeがWorld Spaceか
  • 看板が巨大/極小 → CanvasのScaleが 1 のままかもしれません。0.005 前後にします
  • ClientSimで人数が増えない → ClientSimでは他のプレイヤーが本物ではありません。Build & Testで2人にして確かめます
  • 人数が実際と合わない → 変数で足し引きしていませんか。GetPlayerCount() で取り直します
Sponsored

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

  • isLocal で自分だけ処理できる: player.isLocaltrue なら、そのイベントは自分についてのものです。「自分が入ったときだけ案内を出す」といった処理に使います
  • displayName で名前が取れる: ログや歓迎メッセージに使えます。ただし表示する場合は、長い名前や特殊な文字も来ることを想定しておきます
  • 全員のリストも取れる: VRCPlayerApi.GetPlayers() で配列として取得できます。ただし呼ぶたびに配列を作るので、毎フレーム呼ぶのは避けます
  • 入った直後は準備が整っていないことがある: 参加した瞬間にそのプレイヤーの位置を読もうとすると、まだ確定していない場合があります。少し待ってから読むほうが安全です(時間差で処理を呼ぶ
  • Utilities.IsValid() で確認する: プレイヤーが既に退出している場合があるので、保存しておいた参照を使う前に確認します

まとめ

プレイヤーイベントは、2つの軸で考えます。

  • 誰のPCで呼ばれるか → その場にいる全員のPC
  • 誰について呼ばれるか → 引数の player
  • 自分が入ったときは、既にいた人の分も全部呼ばれる
  • 人数は変数で数えず、GetPlayerCount() で取り直す

作るときの問いかけは、「この値は自分で覚えておくべきか、それとも聞き直せるか」 です。聞き直せるなら、そのほうがずれません。

次は、複数のオブジェクトをまとめて扱います。配列入門 で、3灯のライトを順番に切り替えてみましょう。

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