mcpField
V
vrc-udon

vrc-udon

github.com/alexanderstephenthompson開発47 回インストール
リポジトリ

vrc-udon について

vrc-udonは、UdonSharpでVRChatワールドのスクリプトを書くための開発スキルです。ネットワーク、所有権、同期、途中参加プレイヤーの処理を中心に扱います。

主な機能

  1. 01UdonSharpの構文とパターン
  2. 02ネットワークと変数同期
  3. 03所有権移譲の指針
  4. 04途中参加プレイヤーの状態処理
  5. 05イベント駆動のスクリプト通信

活用シーン

  1. 01VRChatワールド向けのUdonスクリプト作成
  2. 02ネットワーク上のプレイヤー間で状態を同期
  3. 03同期変数の変更前に所有権を処理
  4. 04途中参加プレイヤーに正しいワールド状態を表示

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/alexanderstephenthompson/claude-hub --skill vrc-udon

インストール後、Claude Code で/vrc-udonを入力して読み込まれたか確認します。

同梱ファイルreferences/networking.mdassets/udon-checklist.md

詳細

VRChat Udon スキル

Version: 1.0 Stack: VRChat SDK, UdonSharp

Udonは、ネットワーキングを追加するまでは通常のUnityスクリプトのように見えます。しかし、ネットワーキングを追加すると、すべてが変わります。所有権がない状態で同期変数を変更しても、何のエラーも警告もなく、ただ何も起こらずに失敗します。RequestSerializationを忘れると、変更内容が自分のマシンから送信されません。エディターでテストしても、プレイヤーが1人しかいないため、ネットワーキングのバグを検出できません。再シリアライズを明示的に処理しない限り、後から参加したプレイヤーには現在の状態ではなく、デフォルトの状態が表示されます。

このスキルに含まれるすべてのルールは、Udonのデフォルト動作が暗黙のうちに失敗するものであることを踏まえています。


対象範囲と境界

このスキルの対象:

  • UdonSharpの構文とパターン
  • ネットワーキングと同期
  • プレイヤーとのインタラクション
  • ワールドイベント
  • Udonの一般的な動作

以下は他のスキルを参照してください:

  • unity-csharp:C#のパターンとパフォーマンス最適化
  • vrc-worlds:ワールドのセットアップと最適化

このスキルを使う場面: VRChatワールド用のUdonスクリプトを作成するとき。


基本原則

  1. ネットワークの認識 — 同期変数にはそれぞれ帯域幅のコストがかかります。
  2. オーナーモデル — 同期変数を変更できるのはオーナーだけです。
  3. 後から参加するプレイヤー — 後から参加するプレイヤーに対しても、状態が正しく保たれる必要があります。
  4. ローカルとグローバル — ローカルかネットワーク経由かを明確にしてください。
  5. イベント駆動 — ポーリングではなく、SendCustomEventを使ってください。

パターン

基本的なUdonSharpスクリプト
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;

public class MyBehavior : UdonSharpBehaviour
{
    [UdonSynced] private bool _isActive;

    public override void Interact()
    {
        // Take ownership before modifying synced var
        Networking.SetOwner(Networking.LocalPlayer, gameObject);
        _isActive = !_isActive;
        RequestSerialization();
    }

    public override void OnDeserialization()
    {
        // Called when synced vars update from network
        UpdateVisuals();
    }

    private void UpdateVisuals()
    {
        // Update based on _isActive state
    }
}
所有権の移譲パターン
public void TakeOwnershipAndModify()
{
    // Always check and transfer ownership first
    if (!Networking.IsOwner(gameObject))
    {
        Networking.SetOwner(Networking.LocalPlayer, gameObject);
    }

    // Now safe to modify synced variables
    _syncedValue = newValue;
    RequestSerialization();
}
後から参加するプレイヤーへの対応
[UdonSynced] private bool _doorOpen;

public override void OnPlayerJoined(VRCPlayerApi player)
{
    // If we're owner, re-serialize state for the new player
    if (Networking.IsOwner(gameObject))
    {
        RequestSerialization();
    }
}

public override void OnDeserialization()
{
    // Late joiners get current state here
    SetDoorState(_doorOpen);
}
カスタムイベントによる通信
// Script A - sends event
public UdonBehaviour targetScript;

public void OnButtonPress()
{
    targetScript.SendCustomEvent("HandleButtonPress");
}

// Script B - receives event
public void HandleButtonPress()
{
    // Handle the event
}

// Network event (all players)
public void TriggerGlobalEvent()
{
    SendCustomNetworkEvent(NetworkEventTarget.All, "OnGlobalEvent");
}

public void OnGlobalEvent()
{
    // Runs on all players
}

アンチパターン

アンチパターン問題修正方法
所有権なしで同期変数を変更する暗黙のうちに失敗する先にSetOwnerを呼び出してから変更する
RequestSerializationを忘れる変更が同期されない同期変数を変更した後は必ず呼び出す
同期するデータが多すぎるネットワークの遅延同期変数を最小限にする
ネットワークの確認にUpdate()を使うパフォーマンスの無駄OnDeserializationやイベントを使う
後から参加するプレイヤーへの処理がない参加者に正しくない状態が表示されるプレイヤーの参加時に再シリアライズする

チェックリスト

  • 同期変数を変更する前に所有権を移譲した
  • 変更後にRequestSerializationを呼び出した
  • OnDeserializationで視覚的な状態をすべて更新する
  • 後から参加するプレイヤーに対応した(OnPlayerJoined + serialize)
  • グローバルなトリガーにネットワークイベントを使った
  • 同期変数の数を最小限にした

参考資料

  • references/networking.md — Udonのネットワーキング、同期、所有権のパターン

アセット

  • assets/udon-checklist.md — Udonスクリプト開発のチェックリスト

コメント