ボタンを押すとCubeの色が変わるようになりました。でも、VRChatには押し方が何通りもあります。
VRではコントローラのトリガー、デスクトップでは左クリック。しかも「ジャンプした瞬間」や「移動キーを押した量」も受け取れます。似た名前が並んでいて、どれを使えばいいのか迷います。
この記事では、対象への操作(Interact)と、入力そのもの(Input Events) を切り分けて、ログで確かめます。
この記事でわかること
- InteractとInputUseの違い
- Interactが動くために必要な3つの条件
- 操作できる距離の変え方
- VRとデスクトップで同じイベントが来ること
最初のUdonSharp を試した状態から始めます。
「対象への操作」と「入力そのもの」
似ているようで、入口がまったく違います。

- Interact は、「このオブジェクトが 操作された」という通知です。視線の先にあって、届く距離にあるときだけ呼ばれます
- Input Events は、「ボタンが押された」という通知です。何を見ているかに関係なく、そのプレイヤーのPCで呼ばれます
分かりやすい例で言うと、InputUse は「Useボタンを押した」で、Interact は「Useボタンで、あのCubeを操作できた」です。押しても対象がなければ、Interactは呼ばれません。
主なInput Eventsはこれです。
| イベント | 受け取るもの |
|---|---|
InputUse | 使う操作の押下と解放 |
InputJump | ジャンプの押下と解放 |
InputGrab / InputDrop | 掴む・離す |
InputMoveHorizontal / InputMoveVertical | 移動の量(-1〜1) |
InputLookHorizontal / InputLookVertical | 視点を回す量 |
ボタン系は bool(押されたか離されたか)、軸系は float(どのくらいか)を受け取ります。
Input Eventsは、押した本人のPCでしか呼ばれません。 他の人に伝えたいときは、同期の仕組みで結果を送ります。
実践:2つの入口をログで見分ける
同じCubeで、InteractとInput Eventsの両方を受け取って、Consoleで違いを見ます。
1. Cubeを置く
「3D Object → Cube」を作り、InputTestCube と名付けて (0, 1, 1) に置きます。Box Colliderはそのまま、Is Triggerはオフです。
2. 両方を受け取るコードを書く
Assets/Scripts で「Create → U# Script」を選び、InputWatcher を作ります。
using UdonSharp;
using UnityEngine;
using VRC.Udon.Common;
[UdonBehaviourSyncMode(BehaviourSyncMode.None)]
public class InputWatcher : UdonSharpBehaviour
{
// このオブジェクトが操作されたときだけ呼ばれる
public override void Interact()
{
Debug.Log("[InputWatcher] Interact:このCubeが操作された");
}
// Useボタンの押下と解放。何を見ていても呼ばれる
public override void InputUse(bool value, UdonInputEventArgs args)
{
Debug.Log("[InputWatcher] InputUse:" + (value ? "押した" : "離した"));
}
// ジャンプの押下と解放
public override void InputJump(bool value, UdonInputEventArgs args)
{
if (value)
{
Debug.Log("[InputWatcher] InputJump:ジャンプした");
}
}
}
using VRC.Udon.Common; を忘れないでください。UdonInputEventArgs を使うために必要です。
Cubeに Udon Behaviour を追加し、Program Source に InputWatcher を指定します。Interaction Text は 調べる にしておきます。
3. 違いを確かめる
Playして、Gameビューをクリックしてから、Consoleを見ながら操作します。
| 操作 | 出るログ |
|---|---|
| Cubeを見ずに、何もない方向で左クリック | InputUse:押した InputUse:離した だけ |
| Cubeに照準を合わせて左クリック | InputUse:押した に加えて Interact も出る |
| スペースキーでジャンプ | InputJump:ジャンプした |
| Cubeから10m離れて左クリック | InputUse だけ。Interact は出ない |

1行目と2行目の違いが、この記事のポイント です。ボタンは同じ、押した本人も同じ。違うのは「対象に届いたか」だけです。

InputUse は 押したときと離したときの2回 呼ばれます。value が true なら押下、false なら解放です。「押している間だけ何かを動かす」ような処理は、この2回を使って作れます。
Interactが動くための3つの条件
Interactが呼ばれない原因は、ほぼこの3つのどれかです。

- 同じオブジェクトにColliderがある: 空の親にプログラムを付けて、Colliderは子のCubeにある、という構成では動きません
- 届く距離にいる: 既定はおよそ2mです。遠いと照準を合わせても何も出ません
- 視線が通っている: 手前に別のColliderがあると、そちらが優先されます
距離を変えたいときは、Udon Behaviourの Proximity を大きくします。ただし遠くから押せるようにすると、通りすがりに意図せず押される 事故も増えます。必要な範囲にとどめてください。
Interaction Text は、照準を合わせたときに出る案内です。空でもInteractは動き、既定の文字が表示されるだけです。「何が起きるか」が分かる短い言葉にします。
なお、Rigidbodyは不要 です。Interactに必要なのは、Colliderとプログラムだけです。
VRとデスクトップの違い
同じイベ ント名で、どちらの環境からも来ます。ここはUdonが吸収してくれます。
ただし、割り当てと値の性質が違います。
| デスクトップ | VR | |
|---|---|---|
| Use | 左クリック | トリガー |
| Jump | スペース | コントローラのボタン |
| 移動の値 | ほぼ -1 / 0 / 1 | スティックの倒し具合で連続的 |
移動の軸を使うときは、この違いが効いてきます。デスクトップでは押したか押していないかの2択に近く、VRでは中間の値が来ます。
もう1つ大事なのが、メニューを開いているあいだは入力イベントが来ない ことです。しかも、メニューを開いた瞬間に「押していたボタンが離された」扱いになります。押しっぱなしを前提にした処理では、ここで途切れます。
「押している間だけ動く」仕掛けを作るときは、離されたときに必ず止まる ように書いておくと安全です。
おまけ:先に知っておくと良いこと
argsには左右の情報が入る: VRではどちらの手か、デスクトップではキーボードかマウスかが分かります。左右で違う動作をさせたいと きに使えます- Input Eventsは全員のPCで動く: 押した本人にしか届かないので、他の人に伝えるには同期が必要です。ネットワーク同期入門 で扱います
- Interactを無効にできる: Udon Behaviourの
DisableInteractiveをオンにすると、プログラムは動いたまま操作だけ受け付けなくなります。条件付きで押せるボタンを作るときに使います - VRC Pickupと一緒に付けない: 掴む操作が優先されて、Interactが動かなくなります
- 移動の軸を毎フレーム使わない:
InputMoveHorizontalは動かしているあいだ何度も呼ばれます。重い処理を直接書かず、値を変数に入れておいて必要なときに使います
まとめ
入力には、2つの入口があります。
- Interactは「このオブジェクトが操作された」。対象・距離・視線が必要
- Input Eventsは「ボタンが押された」。何を見ていても呼ばれる
- Input Eventsは押した本人のPCだけ。他の人には届かない
- VRとデスクトップは同じイベント名。値の性質だけが違う
書く場所に迷ったときの問いかけは、「これは特定の物への操作か、それともボタンそのものか」 です。前者ならInteract、後者ならInput Eventsです。
次は、複数のボタンから同じ処理を呼びます。メソッドとカスタムイベント へ進むか、押した結果を作り込むなら ボタンで切り替える が実践的です。