Udon サンプルシーン
このシーンには、ワールドで Udon を活用する方法のサンプルが含まれています。Build & Test を実行するか、このワールドを公開して VRChat で試してみてください。
Prefabs
このシーン内の Prefabs は、ボタン、アバターペデスタル、ステーション、ミラーなど、VRChat コンポーネントを使用した一般的なインタラクションを実演するものです。
以下の Prefabs はすべて VRChat Worlds SDK に含まれています。これらは独自のワールドに追加することが可能です。例えば、VRCWorld はほとんどの VRChat シーンにデフォルトで含まれています。

VRCWorld
この prefab を使用すると、Unity シーンを簡単に VRChat へアップロードできます。これには 4 つのコンポーネントが含まれています。
- VRC Scene Descriptor スクリプト: ワールドの基本プロパティを定義します。すべての VRChat ワールドに必須です。
- VRC Pipeline Manager スクリプト: ワールド ID が含まれています。VRC Scene Descriptor に自動的に追加されます。
- VRCWorldSettings Udon Graph プログラム: ワールド内のプレイヤーの移動速度を変更できます。
- Avatar Scaling Settings Udon Graph プログラム: ワールド内のプレイヤーのアバター倍率を制限できます。
自身の Unity シーンで VRCWorld prefab を使用したい場合は、\Packages\com.vrchat.worlds\Samples\VRCPrefabs\VRCWorld.prefab から見つけることができます。
AvatarPedestal
これは prefab として利用可能で、ユーザーがペデスタルに対して Interact した際にアバターを切り替えるプログラムが組み込まれています。これがこの prefab のデフォルトの挙動です。
この prefab のインタラクション距離を変更するには、prefab を展開し、Udon Behaviour コンポーネントの "Proximity" 設定を変更してください。
VRCChair3
これは prefab として利用可能で、StationGraph というプログラムが組み込まれています。プレイヤーがこれに対して Interact するとステーションに着席し、入退室時にプレイヤーの表示名をログに出力します。
MirrorSystem
このオブジェクトには ToggleGameObject プログラムが組み込まれており、Interact イベントを使用して対象オブジェクトを Active/Inactive に切り替えます。この例では、このオブジェクトの子階層にある VRCMirror オブジェクトを制御しています。
Cubes
これらのオブジェクトは、Cubes で行えるシンプルな操作を実演しています。主に ChangeMaterialOnEvent プログラムを再利用して、他のオブジェクトからカスタムイベントをトリガーする方法を示しています。

InteractCube
このオブジェクトには SendEventOnInteract プログラムが組み込まれています。これはプレイヤーがオブジェクトを指差して「use」ボタンを押したときにトリガーされる Interact イベントをリッスンします。この例では、"changeMaterial" というカスタムイベントを子オブジェクトの ChangeMaterialOnEvent プログラムに送信します。これを受け取ると、配列内のマテリアルが切り替わります。これらのプログラムはどちらも再利用可能です。UdonBehaviour コンポーネントのインスペクター上で、SendEventOnInteract プログラムから送信される eventName を変更できます。
TimerCube
このオブジェクトには SendEventOnTimer プログラムが組み込まれています。これは指定された duration (期間) だけタイマーを実行し、その後指定されたイベントを送信します。この例では、"changeMaterial" というカスタムイベントを子オブジェクトの ChangeMaterialOnEvent プログラムに送信します。これを受け取ると、配列内のマテリアルが切り替わります。これらのプログラムはどちらも再利用可能です。UdonBehaviour コンポーネントのインスペクター上で、SendEventOnTimer プログラムから送信される eventName を変更したり、duration (秒単位) を変更してトリガーの間隔を調整したりできます。
UseCube
このオブジェクトの子である Model には SendEventOnUse プログラムが組み込まれています。これはオブジェクトが拾われて「Used」(使用) されたときにイベントを送信できます。この例では、"changeMaterial" というカスタムイベントを MaterialChanger オブジェクト上の ChangeMaterialOnEvent プログラムに送信し、イベント受信時に配列内のマテリアルを切り替えます。これらのプログラムはどちらも再利用可能です。UdonBehaviour コンポーネントのインスペクター上で、SendEventOnUse プログラムから送信される eventName を変更できます。また、Model オブジェクトには VRCObjectSync コンポーネントも組み込まれており、オブジェクトが移動した際に他のユーザーに対してもその動きを同期させます。
Udon 変数同期
これらのオブジェクトは、オブジェクトの所有者からインスタンス内の他の全員へ変数の値を同期させるさまざまな方法を実証するものです。

「Canvas」アイテムには、同期された変数を持つ多数の UI アイテムが含まれています。
ButtonSyncOwner
これはここで説明する最初のプログラムで、Manual Sync メソッドを使用しています。下の画像を見ると、OnClick() ハンドラーがあり、UdonBehaviour.SendCustomEvent を値 "OnClick" で呼び出していることがわかります。これはそのすぐ下にある UdonBehaviour をターゲットにしており、そこでカスタムイベント "OnClick" を実行します。UI 要素が UdonBehaviour 上でイベントを実行する方法はこれです。

Graph Program では、OnClick イベントがクリックしたプレイヤーがオブジェクトの「所有者(Owner)」かどうかをチェックします。所有者である場合、"clickCount" 変数を 1 増やしてから RequestSerialization を呼び出します。これにより、Udon に対してこの Manual 同期された UdonBehaviour のデータを更新するよう通知します。

'Set clickCount' ノードで 'sendChange' トグルがオンになっていることに注目してください。これにより、新しい clickCount の値を受け取ったときに、全員に対してイベントがトリガーされます。

clickCount が更新されると、この Change イベントがトリガーされ、プログラムの「所有者」が誰であるかに関係なく、ボタンのテキストが新しい値に設定されます。
ButtonSyncAnyone
このオブジェクトは、上記の ButtonSyncOwner と非常によく似たプログラムを使用していますが、ボタンをクリックしたユーザーがそのオブジェクトの「所有者ではない」場合のためのロジックが追加されています。その場合、彼らはオブジェクトの「所有者」にカスタムイベント "OnClick" を送信します。これだけです!所有者はこのイベントを受け取り、まるで自分でボタンをクリックしたかのように処理を行います。

ButtonSyncBecomeOwner
このオブジェクトは、お馴染みの ButtonSync プログラムをベースにして、オブジェクトの所有権を簡単に変更する方法を実証します。所有者以外のユーザーがボタンをクリックすると、そのユーザーに所有権が割り当てられ、変数が更新されます。これは、複数の変数を変更したい場合や、単に値をインクリメントするよりも複雑なロジックを実行したい場合に便利です。

オブジェクトの所有権を変更する際は、転送を許可するかどうかを決定するためにロジックが実行されます。詳細については Networking を参照してください。カスタムロジックを追加しない場合、すべての所有権のリクエストが承認されます。以下のノードは、'someSpecialLogic' と呼ばれるブール変数をチェックして転送を承認するかどうかを決定するシンプルなセットアップを示しています。'requester'(リクエスト元)や 'newOwner'(新しい所有者)、あるいはその両方に基づいて独自のロジックを構築できます。

SliderSync

このオブジェクトには SliderSync というプログラムがあり、ButtonSyncBecomeOwner と同様に機能します。誰かがスライダーを動かすと、その人が所有者になり、新しい値を他の全員に送信します。1 つの違いは、UI から "OnValueChanged" イベントがトリガーされた際、この新しい値がスライダーの現在の値と異なっているかどうかがチェックされる点です。これは、Udon からスライダーの値を更新するとこのイベントもトリガーされ、無限ループが発生してしまう可能性があるためです。そのため、ロジックの残りを実行する前に 'sliderValue' 変数がスライダーの値と異なっていることを確認するロジックを組み込んでいます。
また、変数の変更イベントを使用して、誰かが所有者となって値を更新するたびにスライダーの値をテキストフィールドに更新するようにしています。
Toggle
このオブジェクトには、上記の Slider と同様に機能する ToggleSync プログラムがあります。誰かが値を現在の値とは異なる値に変更すると、その人が所有者となり、新しい値を他の全員に送信します。

Dropdown

このオブジェクトには、上記の Toggle や Slider と同様に機能する DropdownSync プログラムがあります。誰かが値を変更すると、それが現在の値と異なっていることを確認してから所有者になり、新しい値を他の全員に送信します。
InputField

このオブジェクトには、上記の Dropdown と同様に動作する InputFieldSync というプログラムが含まれています。誰かが値を変更したとき、その値が以前と異なることを確認し、オブジェクトのオーナーとなって新しい値を他の全員に送信します。
PickupCube

このオブジェクトには VRC Pickup コンポーネントと VRC Object Sync コンポーネントが含まれており、これらによって持ち運びや移動が可能になり、他のユーザーとも自動的に同期されます。UdonBehaviour は、上記の同期プログラムのような「Manual」ではなく「Continuous」に設定されています。これは、Transform を最新の状態に保つために、より頻繁な更新が必要だからです。この UdonBehaviour には SyncPickupColor プログラムが設定されており、オブジェクトを持っている間、滑らかに色を変化させます。これは、Update イベントの実行中に、ローカルプレイヤーがそのオブジェクトの Owner であり、かつ VRCPickup.get isHeld が true であるかを確認することで行われます。同期モードが Continuous に設定されているため、RequestSerialization を使用する必要はありません。値は可能な限り頻繁に自動更新されます。

PickupSphere
このオブジェクトには、実際には Udon が設定されていません!単に VRC Pickup コンポーネントと VRC Object Sync コンポーネントを使用しているだけで、ユーザーが手に取って同期された状態で移動させることができるようになっています。

PlayerDetection
プレイヤーが特定のエリアに侵入したり、物理オブジェクトと衝突したりしたときに反応させることは非常に有用です。これらのサンプルプログラムでは、それを実現するためのいくつかの方法を説明します。
PlayerTrigger

これは、プレイヤーがエリアに出入りすることを検知するために最も一般的に使用される方法です。「TriggerArea」オブジェクトには、半透明の青いマテリアル、IsTrigger にチェックを入れた Box Collider、そして PlayerTrigger プログラムソースを持つ UdonBehaviour が設定されています。
このプログラムでは、プレイヤーがコライダーに出入りするたびに OnPlayerTriggerEnter および OnPlayerTriggerExit イベントが発生します。プログラムはその後、そのプレイヤーの displayName を取得し、ターゲットとなるキャンバス上のテキストを更新します。

PlayerCollision
この構成では、物理オブジェクトがプレイヤーのコライダーに侵入したときに発生する OnPlayerCollisionEnter/Exit イベントをトリガーし、それに応答する方法を示しています。

TriggerArea オブジェクトには、上記の PlayerTrigger プログラムと同様に、プレイヤーがトリガーエリアに侵入したことを検知する FireOnTrigger Udon Program が設定されています。この場合、このイベントは「Fire」というカスタムイベントを Projectile オブジェクトに送信するために使用されます。これにより、Projectile キューブに自身へ力を加える処理が実行され、プレイヤーに向かって移動します。キューブがプレイヤーと衝突すると、そのプレイヤーの displayName がターゲットの Text フィールドに書き込まれます。
ここで使用されている PlayerCollision イベントは、それを経験したプレイヤーのローカル環境でのみ発生することに注意してください。これらのイベントを他のプレイヤーに通知したい場合は、Synced Variables や Custom Network Events を使用して、その機能を自分で実装する必要があります。
PlayerParticleCollision

このデモは上記の PlayerCollision と同様の構成で、Trigger Area を使用して他のイベントを開始します。このケースでは、プレイヤーが Trigger Area に侵入すると、SetActiveFromPlayerTrigger プログラムが CollisionParticles オブジェクトを有効化します。このオブジェクトには ParticleSystem が搭載されており、World Collision と Send Collision Messages が有効になった状態でプレイヤーに向けて発射されます。このオブジェクトにアタッチされた Udon Program PlayerCollisionParticles は、グラフ内で OnPlayerParticleCollision イベントを発生させ、影響を受けたプレイヤーの displayName をターゲットのテキストフィールドに書き込みます。

Udon Sync Player

このセットアップは、Unity / AVPro ビデオプレイヤーを使用してビデオ再生の読み込みと同期を行う方法の一例を示しています。プログラムが大規模なため、専用のページに分けて解説しています。
CubeArraySync

このシンプルなプログラムは、クリックするとランダムに表示・非表示が切り替わるキューブのグリッドを作成します。データ通信量を最小限に抑えつつ配列の同期を行う、その強力さを実証する例です。CubeArraySync プログラムには、25個の値を保持する Boolean 配列である data という変数が含まれています。これは、すべてのユーザー間で同期される25個の単純な「はい/いいえ(オン/オフ)」の値を意味します。また、25個のキューブを格納した cubes という GameObject 配列も持っています。
すべてのキューブを含むオブジェクトが誰かにクリックされると、「Randomize」という Custom Network Event が CubeArraySync オブジェクトのオーナーに送信されます。オーナーは For ループを使用して、0から1の数値を生成し、その値が 0.5 より大きいかどうかを確認することで、各値をランダムにオンまたはオフに設定します。配列変数を更新したら RequestSerialization を呼び出し、続いてカスタムイベント UpdateCubes を呼び出します。

UpdateCubes イベントは別の For ループを使用して、配列内の各「はい/いいえ」変数を順に処理し、対応する Cube の表示・非表示を設定します。このイベントは、配列を更新した後のオーナーによって、あるいは VRChat が他のすべてのユーザーに対して配列変数を更新した後の OnDeserialization によってトリガーされます。ここで OnVariableChange ではなく OnDeserialization を使用しているのは、配列変数では現在 Variable Change イベントが発生しないためです。そのため、OnDeserialization で新しいデータを受け取るまで待機し、その時点でシーンを更新するようにしています。
ObjectPool

Object Pool は、オブジェクトのコレクションを管理するのに役立つコンポーネントです。このコンポーネントは、オブジェクトの Active 状態を自動的に同期します。このサンプルプログラムでは、空から箱を1つずつ落として積み重ね、箱をクリックするとその箱が消滅し、再び空からスポーンする様子を確認できます。
これを実現するために、ObjectPool プログラムはシンプルなタイマーを実行し、一定の間隔でオブジェクトの Spawn を試みます。プール内の各 Pooled Box には、シンプルな Pooled Box プログラムが割り当てられています。このプログラムは、Start 時に初期位置を保存し、有効化(プールによってスポーンされた時に発生)されるたびにその位置に復元し、クリックされると各オブジェクトをプールに返却するように動作します。
Simple Pen System
シンプルなペンであっても作成にはそれなりの手間がかかるため、このサンプルについては個別のページで解説します。
最終更新: