PlayerObject
PlayerObjectを使用すると、ワールドに参加した各プレイヤーに対して、懐中電灯や体力バー、剣といったGameObjectのコピーを自動的に割り当てることができます。
- VRChatは、プレイヤーがワールドに参加するたびに、そのGameObjectのコピーを各プレイヤーに対して自動的にスポーンさせます。
- コピーには、元の PlayerObject Template に含まれるすべてのコンポーネントと子GameObjectが含まれます。
- コピーは、元のテンプレートと同じ位置、回転、スケール、および親階層でスポーンされます。
セットアップ
以下の手順に従って、シンプルな PlayerObject を作成します。プレイヤーがインスタンスに参加すると、VRChat はそのプレイヤーのために PlayerObject をスポーンします。
- シーンのヒエラルキーに GameObject を作成します。
VRCPlayerObjectコンポーネントを追加します。- これにより、GameObject が PlayerObject テンプレートになります。
- (任意)GameObject(またはその子要素のいずれか)に
UdonBehaviourコンポーネントを追加します。 - (任意)同期変数を永続化させたい場合は、
UdonBehaviourと同じ GameObject にVRCEnablePersistenceを追加します。
永続ユーザーデータの読み込み
VRChatは、以下の条件を満たす PlayerObject 上の永続ユーザーデータを自動的に読み込みます。
PlayerObject(またはその子GameObject)がUdonBehaviourコンポーネントを持っていること。UdonBehaviourに同期された変数があること。UdonBehaviourのGameObjectがVRCEnablePersistenceコンポーネントも持っていること。
PlayerObject のユーザーデータの読み込みが完了したことを検知するには、OnPlayerRestored を使用してください。このイベントは、PlayerObject のオーナーを含むインスタンス内のすべてのプレイヤーに対して1回ずつ実行されます。
OnPlayerRestored には、データが復元されたプレイヤーへの参照が含まれています。これを利用して、GameObjectのオーナーに変数を初期化させたり、イベントを実行させたりすることができます。
Start および OnDeserialization イベントでは、所有権が正しく保証されています。ただし、OnPlayerRestored イベントが発生する前に PlayerObject のユーザーデータを読み書きすることは避けてください。古いユーザーデータを誤って読み書きしてしまい、VRChatサーバーからユーザーデータを受信した際に変更が上書きされてしまう可能性があります。
所有権
プレイヤーが PlayerObject を所有している場合、その PlayerObject 内にある同期された UdonBehaviours を持つすべての GameObject も自動的にそのプレイヤーが所有することになります。これらを他のプレイヤーに譲渡することはできません。
これは、他のプレイヤーに「盗まれる」ことのないツールやピックアップをプレイヤーに提供する場合に便利です。プレイヤーが自身の PlayerObject を常に所有していることを保証できます。
PlayerObjectテンプレート
PlayerObjectテンプレートは、VRCPlayerObjectを追加してエディタ上で作成するオリジナルのGameObjectです。VRChatは、プレイヤーが参加した際にこのテンプレートを複製してPlayerObjectを生成します。
テンプレートおよびPlayerObject上のコンポーネントは、他のコンポーネントへの参照を持つことができます。
- テンプレートは、それ自身のコンポーネントや子コンポーネントを参照できます。
- テンプレートは、シーン内の他のコンポーネントを参照できます。
- シーン内のコンポーネントからテンプレートを参照することはできません。
- 代わりに、シーン内のオブジェクトは、生成されたPlayerObjectを直接参照する必要があります。
- テンプレートはVRChatによって自動的に無効化されますが、シーン内には存在し続けます。
- 無効化された後のテンプレートを変更、破棄、編集しないでください!これを行うと、エラーや予期しない動作を引き起こす可能性があります。
スクリプト内でPlayerObjectやそのコンポーネントへの参照を取得するには、以下のメソッドを使用します。
Networking.GetPlayerObjectsを使用してプレイヤーに関連付けられたすべてのPlayerObjectを取得し、その配列を走査して特定のオブジェクトを探してください。Networking.FindComponentInPlayerObjectsを使用して、PlayerObjectテンプレートへの参照を特定のプレイヤーのPlayerObjectへと変換してください。- 下記の例を参照してください。
イベント
PlayerObjectに関連するイベントは以下の通りです。
| イベント | 出力 | 備考 |
|---|---|---|
| OnPlayerRestored | VRCPlayerApi player | VRChatプレイヤーの永続データがすべて読み込まれた後にトリガーされます。 |
| OnPersistenceUsageUpdated | VRCPlayerApi player | VRChatプレイヤーの永続化データ使用状況が更新された時にトリガーされます。 |
| OnPlayerObjectStorageExceeded | VRCPlayerApi player | VRChatプレイヤーのPlayer Object使用量が許可された保存制限を超えた時にトリガーされます。 |
| OnPlayerObjectStorageWarning | VRCPlayerApi player | VRChatプレイヤーのPlayer Object使用量が許可された保存制限に近づいた時にトリガーされます。 |
メソッド
PlayerObjectのメソッドは VRC.SDKBase.Networking 名前空間にあります。
| Function | Input | Output | Notes |
|---|---|---|---|
| GetPlayerObjects | VRCPlayerApi target | GameObject[] objects | 指定されたプレイヤーに関連付けられているすべてのPlayerObjectの配列を返します。 |
| FindComponentInPlayerObjects | VRCPlayerApi player, Component referenceComponent | Component | PlayerObjectテンプレートの子である必要がある referenceComponent を使用して、指定されたプレイヤーに関連付けられた対応するコンポーネントを返します。 |
| GetPlayerObjectStorageLimit | int | Player Objectのストレージ制限(バイト単位)を返します。 | |
| GetPlayerObjectStorageUsage | VRCPlayerApi target | int | 対象プレイヤーの最後に計算されたPlayer Objectストレージの使用量を返します。 |
| RequestStorageUsageUpdate | void | ローカルプレイヤーのPlayerDataおよびPlayerObjectのストレージ使用量の計算を要求します。結果は OnPersistenceUsageUpdated を経由して送られます。 |
ストレージ情報は時間が経つと古くなる可能性があり、更新が必要になる場合があります。RequestStorageUsageUpdate を頻繁に呼び出すことは避けてください。
これらのメソッドのユーティリティラッパーは VRCPlayerApi クラスにあります。
| Function | Input | Output | Notes |
|---|---|---|---|
| GetPlayerObjects | GameObject[] objects | 指定されたプレイヤーに関連付けられているすべてのPlayerObjectの配列を返します。 |
例
PlayerObject 上のカスタムスクリプトを見つける
この例では、すべての PlayerObject を自動的に検索し、探している特定のコンポーネントを見つけます。CustomPlayerObjectScript を、見つけたいコンポーネントの型に置き換えてください。
public CustomPlayerObjectScript Find(VRCPlayerApi player)
{
var objects = Networking.GetPlayerObjects(player);
for (int i = 0; i < objects.Length; i++)
{
if (!Utilities.IsValid(objects[i])) continue;
CustomPlayerObjectScript foundScript = objects[i].GetComponentInChildren<CustomPlayerObjectScript>();
if (Utilities.IsValid(foundScript)) return foundScript;
}
return null;
}
PlayerObject 上のコンポーネントを見つける
この例では、FindComponentInPlayerObjects 関数を使用して、PlayerObject テンプレートからの参照を、特定のプレイヤーの PlayerObject からの参照に変換します。
public Transform referenceChildTransform; // A reference to a Transform on a PlayerObject or a child of a PlayerObject
public void Find(VRCPlayerApi targetPlayer)
{
Component foundComponent = Networking.FindComponentInPlayerObjects(targetPlayer, referenceChildTransform);
// foundComponent will be of type Transform and will correspond to the targetPlayer's PlayerObject that matches the reference.
}
最終更新: