概要
VRChatのワールドは、プレイヤーが存在して初めて意味を持ちます。プレイヤーがワールドに参加したり、ワールド内で特定のアクションを起こしたりした時に、それに応じたギミックを作動させることは、ワールドをよりダイナミックで魅力的なものにします。
UdonSharpには、プレイヤーに関する様々な出来事を検出するためのイベントが多数用意されています。本記事では、これらのプレイヤーイベントの中から特に重要なものをピック アップし、その使い方と活用例を解説します。
これらのイベントは、引数として**VRCPlayerApi**オブジェクトを取ることが多く、このオブジェクトを通じて、イベントを発生させたプレイヤーの情報(名前、IDなど)にアクセスできます。
1. プレイヤーの参加と退出
ワールドにプレイヤーが出入りするのを検出するイベントは、ソーシャルな機能やゲーム管理の基本となります。
OnPlayerJoined(VRCPlayerApi player)
- 実行タイミング: 新しいプレイヤーがインスタンスに参加し、ロードが完了した時に、インスタンス内の全プレイヤーのクライアントで呼び出されます。
- 引数: 参加したプレイヤーの
VRCPlayerApiオブジェクト。 - 主な用途:
- 参加ログの表示(例: 「Taroさんが参加しました」)。
- プレイヤーリストの更新。
- ゲームの参加人数をカウントし、定員に達したらゲームを開始する。
OnPlayerLeft(VRCPlayerApi player)
- 実行タイミング: プレイヤーがインスタンスから退出した時に、インスタンス内に残っている全プレイヤーのクライアントで呼び出されます。
- 引数: 退出したプレイヤーの
VRCPlayerApiオブジェクト。 - 主な用途:
- 退出ログの表示。
- プレイヤーリストから名前を削除す る。
- ゲームマスターが退出した場合に、新しいマスターを選出する。
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
public class PlayerJoinLeaveLogger : UdonSharpBehaviour
{
public override void OnPlayerJoined(VRCPlayerApi player)
{
// 参加したプレイヤーが自分自身でない場合のみメッセージを表示
if (player.isLocal)
{
Debug.Log("ワールドへようこそ!");
}
else
{
Debug.Log($"{player.displayName}さんがワールドに参加しました。");
}
}
public override void OnPlayerLeft(VRCPlayerApi player)
{
// プレイヤーが存在しない場合(エラー対策)
if (player == null) return;
Debug.Log($"{player.displayName}さんがワールドから退出しました。");
}
}
2. プレイヤーの死亡とリスポーン
アスレチックや戦闘ゲームなどでは、プレイヤーの死亡(落下など)とリスポーン(復活)を扱う必要があります。
OnPlayerRespawn(VRCPlayerApi player)
- 実行タイミング: プレイヤーがVRChatのメニューから「Respawn」をクリックしたとき、またはVRC Scene Descriptorで設定されたリスポーン高度より下に落下したときに、そのリスポーンしたプレイヤー自身のクライアントでのみ呼び出されます。
- 引数: リスポーンしたプレイヤーの
VRCPlayerApiオブジェクト。 - 主な用途:
- 体力やスコア、所持アイテムのリセット。
- リスポーン時に一時的な無敵時間を与える。
重要:
VRCPlayerApi.Respawn()をスクリプトから呼び出しても、OnPlayerRespawnイベントは発火しません。スクリプトからリスポーンさせる場合に追加の処理が必要な場合は、Respawn()を呼び出す直前または直後に、その処理を直接実行するように設計してください。
// プレイヤーの体力を管理するスクリプトの例
public class PlayerHealth : UdonSharpBehaviour
{
private int health = 100;
// プレイヤーがダメージを受けた時に呼ばれるカスタムイベント
public void TakeDamage(int damage)
{
health -= damage;
if (health <= 0)
{
// 体力が0以下になったらリスポーンさせる
// 注意: Respawn()ではOnPlayerRespawnは発火しないため、
// リセット処理を直接呼び出す
ResetHealth();
Networking.LocalPlayer.Respawn();
}
}
// 体力をリセットする処理
private void ResetHealth()
{
health = 100;
Debug.Log("体力が全回復しました。");
}
// メニューからのリスポーン時や落下時に呼ばれる
public override void OnPlayerRespawn(VRCPlayerApi player)
{
ResetHealth();
}
}
3. アバターに関するイベント
プレイヤーが使用するアバターに関する変更を検出することもできます。
OnAvatarChanged(VRCPlayerApi player)
- 実行タイミング: プレイヤーがアバターを変更した時に、そのプレイヤー自身のクライアントでのみ呼び出されます。
- 引数: アバターを変更したプレイヤーの
VRCPlayerApiオブジェクト。 - 主な用途:
- 特定のアバターでのみ動作するギミックの有効化/無効化。
- アバターの身長(スケール)を測定し、それに応じてギミックの挙動を調整する。
OnAvatarEyeHeightChanged(VRCPlayerApi player, float eyeHeight)
- 実行タイミング: プレイヤーのアバターの視点の高さが変化した時(キャリブレーション時など)に、インスタンス内の全プレイヤーのクライアントで呼び出されます。
- 主な用途:
- プレイヤーの身長に合わせてUIの位置を調整する。
4. ピックアップ(物を掴む)に関するイベント
VRCPickupコンポーネントがアタッチされたオブジェクトをプレイヤーが掴んだり離したりした時にもイベントが発生します。
OnPickup()
- 実行タイミング: プレイヤーがこのオブジェクトを掴んだ瞬間に呼び出されます。
OnDrop()
- 実行タイミング: プレイヤーがこのオブジェクトを離した瞬間に呼び出されます。
OnPickupUseDown() / OnPickupUseUp()
- 実行タイミング: オブジェクトを持っている状態で、Useボタン(VRのトリガーなど)を押した瞬間 (
UseDown) / 離した瞬間 (UseUp) に呼び出されます。 - 主な用途: 銃のトリガー、懐中電灯のスイッチなど、持った状態で操作するアイテムの実装。
// 懐中電灯のスクリプト例
public class Flashlight : UdonSharpBehaviour
{
public Light flashlight;
// 持っている状態でトリガーを引いたらライトを切り替える
public override void OnPickupUseDown()
{
flashlight.enabled = !flashlight.enabled;
}
}
まとめ
- プレイヤーに関するイベントを利用することで、プレイヤーの行動や状態変化に応じたインタラクティブなギミックを作成できます。
OnPlayerJoined/OnPlayerLeftは、プレイヤーの出入りを検出し、全プレイヤーで実行されます。OnPlayerRespawnは、プレイヤーのリスポーンを検出し、本人のみで実行されます。OnAvatarChangedは、アバターの変更を検出し、本人のみで実行されます。OnPickup系のイベントは、物を掴んだり離したり、使ったりする操作を検出します。- これらのイベントの多くは、引数として
VRCPlayerApiオブジェクトを取り、誰がそのイベントを引き起こしたかの情報を得ることができます。
これらのプレイヤーイベントをマスターすることで、単に動くだけのギミックから、プレイヤーの存在を意識した、より没入感の高いワールド体験を創造することが可能になります。