同期変数で扉の状態は共有できる ようになりました。でも、こういうものは変数にしづらいです。
「いまチャイムを鳴らす」「いま花火を打ち上げる」。その瞬間だけ起きればよくて、あとに残す必要がない ものです。
こういうときに使うのが Network Events です。この記事では、押すと全員にチャイムが鳴る仕掛けを作ります。
この記事でわかること
- 「残る状態」と「その場の合図」の使い分け
- 送り先の3種類(All / Others / Owner)
- 途中参加の人には届かないこと
- 連打されたときの対策
ネットワーク同期入門 を試した状態から始めます。
変数は黒板、イベントは叫び
同期入門で使ったたとえが、ここでも効きます。
同期変数は黒板 です。書いておけば、あとから入ってきた人も読めます。だから「いま開いているか」のような状態に向いています。
Network Eventsは叫び です。その場にいる人には届きますが、声は残りません。あとから来た人には届きません。

使い分けは、この問いかけで決まります。
あとから来た人にも、これを知っていてほしいか?
| 伝えたいもの | イエス/ノー | 使うもの |
|---|---|---|
| 扉が開いているか | イエス | 同期変数 |
| ライトが点いているか | イエス | 同期変数 |
| ゲームの得点 | イエス | 同期変数 |
| いま鳴らすチャイム | ノー | Network Event |
| いま上がる花火 | ノー | Network Event |
| 誰かが正解したブザー | ノー | Network Event |
「過去の効果音を鳴らし直す必要はない」と考えれば、イベントで足ります。逆に、扉の状態をイベントだけで伝えると、あとから入った人の画面では閉じたままになります。
実践:全員にチャイムを鳴らす
ボタンを押すと、その場にいる全員の画面でチャイムが鳴ります。
1. ボタンと音を置く
床のあるシーンに2つ置きます。
| 名前 | 作り方と設定 |
|---|---|
ChimeButton | Cube。(0, 1, 1)、Scale (0.4, 0.4, 0.4) |
ChimeSource | Create Empty に Audio Source を追加。(0, 2, 0) |

ChimeSource の Audio Source には短い効果音を入れ、Play On Awake をオフ、Loop もオフ にします。ボタンで鳴らすので、勝手に鳴っては困ります。
Spatial Blend は 0(2D)にしておくと、部屋のどこにいても同じ音量で聞こえます。
2. コードを書く
Assets/Scripts で「Create → U# Script」を選び、ChimeBell を作ります。
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon.Common.Interfaces;
[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class ChimeBell : UdonSharpBehaviour
{
[SerializeField] private AudioSource chime;
[SerializeField] private float cooldownSeconds = 1f;
private float nextAllowedTime;
public override void Interact()
{
// 連打を弾く
if (Time.time < nextAllowedTime) return;
nextAllowedTime = Time.time + cooldownSeconds;
// その場の全員(自分を含む)で PlayChime を実行してもらう
SendCustomNetworkEvent(NetworkEventTarget.All, nameof(PlayChime));
}
// ネットワークから呼ばれるメソッドには NetworkCallable を付ける
[NetworkCallable]
public void PlayChime()
{
if (chime != null) chime.Play();
Debug.Log("[ChimeBell] 鳴りました");
}
}
3つのポイントがあります。
[NetworkCallable] が必要です。 これがないとネットワーク越しに呼び出せません。しかもエラーは出ず、ただ何も起きないので原因に気づきにくくなります。
NetworkEventTarget.All には自分も含まれます。 念のためと思って PlayChime() を自分でも呼ぶと、音が二重に鳴ります。 送るだけで十分です。
nameof() を使っています。 メソッド名を文字列で書くと、あとで名前を変えたときに黙って動かなくなります。
[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)] を付けているのは、同期モードが None だとネットワークイベントを送れないためです。同期変数を使っていなくても、この指定は必要です。
3. 割り当てて確かめる
ChimeButton に Udon Behaviour を追加し、ChimeBell を指定します。Chimeに ChimeSource をドラッグして、Interaction Text を チャイムを鳴らす にします。
Build & Test で Number of Clients を 2 にして確かめます。
| 順序 | 操作 | 期待する結果 |
|---|---|---|
| 1 | Aが押す | AとB、両方の画面で音が鳴る |
| 2 | Aが素早く連打する | 1秒に1回だけ鳴る |
| 3 | Bが入り直す | 何も鳴らない(過去の音は届かない) |
3番目が、イベントの性質そのものです。叫びは残りません。
送り先を選ぶ
NetworkEventTarget には3つの選択肢があります。

| 送り先 | 誰で実行されるか | 使いどころ |
|---|---|---|
All | 自分を含む全員 | チャイム、花火、ブザー |
Others | 自分以外 | 自分は先にローカルで鳴らしたいとき |
Owner | そのオブジェクトの所有者 | 所有者に処理を依頼するとき |
Others を使う場面は限られます。自分の分だけ即座に鳴らして、ネットワークの往復を待たずに反応を返したいときです。その場合、自分の分は自分で呼びます。
Owner は少し違う使い方をします。「同期変数を書けるのは所有者だけ」 という制約があるので、所有者以外が状態を変えたいときは、所有者へ依頼します。
// 得点を加算してほしい、と所有者に頼む
SendCustomNetworkEvent(NetworkEventTarget.Owner, nameof(AddScore));
得点の加算のように「取りこぼしが困る」処理では、全員が勝手に書き換えるより、所有者1人が受け付けて処理する ほうが確実です。所有権の話は 所有権を理解する を参照してください。
うまくいかないときは
- 自分だけ鳴る →
SendCustomNetworkEventではなく、直接メソッドを呼んでいます - 誰も鳴らない →
[NetworkCallable]が付いているか、メソッドがpublicか確認します - 音が二重に鳴る →
Allで送ったうえに、自分でもメソッドを呼んでいます - 同期モードのエラーが出る →
BehaviourSyncMode.Noneではネットワークイベントを送れません。Manualにします - UIボタンから鳴らすと自分だけ → ボタンの On Click は「送る側」のメソッドにつなぎます。受け取る側のメソッドに直接つなぐと、押した人だけで実行されます
おまけ:先に知っておくと良いこと
- 連打には対策を入れる: 短時間に大量のイベントを送ると、通信が詰まって他の同期にも影響します。前回からの経過時間で弾くのが簡単です

- 引数も渡せる: ネットワークイ ベントには値を付けて送ることもできます。ただし個数と型に制限があるので、複雑なデータは同期変数で持つほうが確実です
- 状態と組み合わせる: 「扉を開ける」は同期変数、「開くときの音」はイベント、という組み合わせが実用的です。役割で分けます
- 確実に届くとは限らない: ネットワークの状況によっては届かないことがあります。効果音なら問題ありませんが、進行に関わる処理をイベントだけに頼るのは避けます
- 使いどころはいろいろ: クイズの正解ブザー、イベント会場の開始合図、ゲームのスタートカウント、拍手の演出。どれも「その瞬間だけ」の処理です
まとめ
Network Eventsは、その場の全員に処理を実行してもらう仕組みです。
- 残る状態は同期変数、その場の合図はイベント
[NetworkCallable]を付けたpublicメソッドを、nameofで指定して送るAllには自分も含まれる。自分でも呼ぶと二重になる- 途中参加の人には届かない
使う前の問いかけは、「あとから来た人にも、これを知っていてほしいか」 です。ノーならイベントです。
持ち物の位置を共有するなら VRC Object Sync、設定を次回まで残すなら PlayerDataで音量を保存する へ進んでください。