【VRChat】VRC Object Sync:投げた物の位置を全員で共有する

作成: 2026-09-08最終更新: 2026-09-09

持てる小物にVRC Object Syncを付けて、投げた位置を全員で共有します。位置は自動で運ばれるが、点灯などの状態は別に同期が要る理由も解説します。

持てるコップを作りました。ところが友達と入ってみると、自分が机に置いたコップが、相手の画面ではまだ床に落ちたままです。

Pickupは掴めるようにするだけの部品で、位置を共有する機能は持っていません。 これを足すのが VRC Object Sync です。

この記事では、投げた物の位置が全員でそろう ところまでを作ります。あわせて、位置以外の状態は別扱いになる理由も見ていきます。

投げたコップが、2人の画面で同じ位置を飛んでいる

この記事でわかること

  • Object Syncが運ぶもの、運ばないもの
  • Pickupと組み合わせたときの所有権の動き
  • 初期位置へ戻す方法
  • 付けるべきもの、付けるべきでないもの

Pickupで持てる懐中電灯を作るネットワーク同期入門 を試した状態から始めます。

Sponsored


運ばれるのは位置と回転だけ

VRC Object Sync は、そのオブジェクトの 位置と回転 を、所有者から他の全員へ送り続ける部品です。

Object Syncは位置と回転を運ぶが、点灯などの状態は運ばない

運ばれるのはこれだけです。色が変わった、ライトが点いた、といった状態は含まれません。

ここを取り違えると、「持ち運びは共有されるのに、懐中電灯の光だけ自分にしか見えない」という状態になります。光は別に同期する必要があるからです。

構成はこうなります。

部品役割
Collider + Rigidbodyぶつかる、落ちる
VRC Pickup掴めるようにする
VRC Object Sync位置と回転を共有する
持てて、落ちて、位置が共有される。3つの部品の組み合わせ

もう1つ、所有権が自動で移る のがPickupの便利なところです。掴んだ瞬間にその人がOwnerになるので、位置を送る役も自動的に切り替わります。追加のコードは要りません。

Sponsored

実践:投げられるコップを作る

持てるコップを作って、投げた位置が全員で同じになるようにします。

1. コップを作る

「3D Object → Cube」で SharedCup を作り、(0, 1, 1)、Scale (0.15, 0.2, 0.15) に置きます。

「Add Component」で次を追加します。

  1. VRC Pickup(Rigidbodyも一緒に付きます)
  2. VRC Object Sync

VRC Pickupの設定は、Auto Hold をオン、Pickupable をオンにします。

Rigidbodyは Use Gravity をオンのまま、Is Kinematic はオフのままです。投げたら落ちる、という自然な動きになります。

追加するのはこれだけです。 コードは書きません。

2. 2人で確かめる

Build & Test で Number of Clients を 2 にして起動します。

順序操作期待する結果
1AとBが入る両方の画面で、同じ場所にコップがある
2Aが掴むAの手にコップが移る。Bの画面でも、Aの手のあたりに動く
3Aが投げる両方の画面で、同じように飛んで落ちる
4Bが拾う所有権がBに移る。Aの画面でもBの手に見える
5Bが持ったままAが退出コップはBの手に残る

コードを1行も書いていないのに、ここまで動きます。 Pickupが所有権を運び、Object Syncが位置を運んでいるからです。

3. 初期位置に戻せるようにする

投げたコップが床の下や壁の向こうへ行くと、拾えなくなります。戻すボタンを作っておくと安心です。

持ち物を初期位置へ戻す

「3D Object → Cube」で ResetButton を作り、(1.5, 1, 1) に置きます。

Assets/ScriptsCupResetter を作ります。

using UdonSharp;
using UnityEngine;
using VRC.SDK3.Components;
using VRC.SDKBase;

[UdonBehaviourSyncMode(BehaviourSyncMode.None)]
public class CupResetter : UdonSharpBehaviour
{
    [SerializeField] private VRCObjectSync targetSync;

    public override void Interact()
    {
        if (targetSync == null) return;

        // 戻す前に、自分が所有者になる
        if (!Networking.IsOwner(targetSync.gameObject))
        {
            Networking.SetOwner(Networking.LocalPlayer, targetSync.gameObject);
        }

        targetSync.Respawn();   // 最初の位置へ戻す
        Debug.Log("[CupResetter] 戻しました");
    }
}

Respawn() は、Object Syncが覚えている最初の位置 へ戻すメソッドです。位置を自分で記録しておく必要はありません。

戻す前に所有権を取っている のがポイントです。位置を動かせるのは所有者だけなので、他の人が持っているコップを戻したいときは、まず所有権を取ります。

ResetButton に Udon Behaviour を追加し、Target Syncに SharedCup をドラッグします。

位置以外の状態は、自分で同期する

ここで、Pickupで作った懐中電灯 を思い出してください。持ったままUseで点灯する仕掛けでした。

これに Object Sync を足すと、持ち運びは共有されますが、光は自分にしか見えません。

理由はもう分かると思います。Object Syncが運ぶのは位置と回転だけで、Light.enabled は運ばれないからです。

光も共有するには、同期変数を1つ足します。

[UdonSynced] private bool beamOn;

public override void OnPickupUseDown()
{
    // 持っている人が所有者になっているので、そのまま書ける
    beamOn = !beamOn;
    ApplyBeam();
    RequestSerialization();
}

public override void OnDeserialization()
{
    ApplyBeam();
}

private void ApplyBeam()
{
    if (beam != null) beam.enabled = beamOn;
}

同期入門とまったく同じ形 です。状態を1つ持って、受け取ったら反映する。対象が扉からライトに変わっただけです。

なお、この場合の同期モードは Manual にします。位置は Object Sync が別に運んでくれるので、こちらは「変わったときだけ」で足ります。

Sponsored

うまくいかないときは

  • 位置が共有されない → VRC Object Syncが付いているか確認します。Pickupだけでは共有されません
  • 持ったのに相手の画面で動かない → 所有権が移っていない可能性があります。Pickupが正しく付いているか確認します
  • 物が震える、飛んでいく → Rigidbodyの設定を見ます。複数のスクリプトが同じ物の位置を触っていないかも確認します
  • 戻すボタンが効かない → 所有権を取ってから Respawn() を呼んでいるか確認します
  • 光だけ共有されない → 仕様です。位置以外の状態は自分で同期します

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

  • 数を絞る: Object Syncは位置を送り続けるので、数が増えるほど通信が増えます。転がる小物は数個までにして、動かない飾りには付けません
  • 動かない物には付けない: 家具や壁に付けても意味がなく、通信だけが増えます
  • スイッチや椅子には合わない: 「全部にObject Syncを付ければ共有できる」という誤解がありますが、位置を送る部品なので、状態を共有したいものには向きません。そちらは同期変数です
  • 物理は完全には一致しない: 各自のPCで物理計算が走るので、細かい転がり方は少しずつ違います。位置は定期的にそろえられますが、途中の動きは厳密には同じになりません
  • 使いどころはいろいろ: ボードゲームの駒、投げて遊ぶボール、カフェのコップ、脱出ゲームの鍵。「動かして、その位置を共有したい」ものすべてです

まとめ

Object Syncは、位置を運ぶ専用の部品です。

  • 運ぶのは位置と回転だけ。点灯などの状態は運ばれない
  • Pickupと組み合わせると、掴んだ人が自動で所有者になる
  • Respawn() で最初の位置へ戻せる。所有権を取ってから呼ぶ
  • 位置以外の状態は、同期変数で自分で共有する

付ける前の問いかけは、「これは、動いた位置を共有したい物か」 です。状態を共有したいだけなら、同期変数のほうが向いています。

各自の設定を次回まで残すなら PlayerDataで音量を保存する、決まった数の物を貸し出すなら VRCObjectPool へ進んでください。

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