ワールドにコップやペンを置い て、手に取れるようにしたい。持ったまま歩いて、机に置き直せるようにしたい。
VRChatにはこれ専用の部品があります。ただ、そのまま付けると 床に沈んだり、放した瞬間に飛んでいったり します。組み合わせに条件があるからです。
この記事では、持てる懐中電灯を作り、Useボタンで点灯させる ところまでを解説します。
この記事でわかること
- Pickupに必要な3つの部品
- 掴む・使う・離すのイベント
- 飛んでいく、沈むといった問題への対処
- 握り位置を整える方法
変数と参照 を試した状態から始めます。
Pickupは3つの部品でできている
持てる物を作るには、3つがそろっている必要があります。

| 部品 | 役割 |
|---|---|
| Collider | 掴む判定と、物にぶつかる形 |
| Rigidbody | 手を離したときに落ちる、転がる |
| VRC Pickup | 掴めるようにする |
この3つは、同じGameObjectに付ける必要があります。 子オブジェクトにColliderがある構成では動きません。ここが最初のつまずきです。
VRC Pickup を追加すると、Rigidbodyが自動で付くことがあります。それでも、Colliderが同じ階層にあるかは自分で確認してください。
主な設定は3つ覚えれば足ります。
| 設定 | 意味 |
|---|---|
Pickupable | いま掴めるかどうか。オフにすると掴めなくなる |
Auto Hold | 掴んだあと手に持ち続けるか |
Proximity | 掴める距離 |
Auto Hold は動きが変わるので、試して確かめる価値があります。オンなら「掴んだら持ちっぱなし」、オフなら「ボタンを押しているあいだだけ持つ」になります。懐中電灯のように使いながら持つ物は、オンが向いています。
実践:持てる懐中電灯を作る
持てる小物を作って、持ったままUseボタンで光を点けます。

1. 懐中電灯を組み立てる
「Create Empty」で Flashlight を作り、(0, 1, 1) に置きます。TransformのRotationとScaleは初期値のままです。
その子に、次の3つを作ります。
| 子の名前 | 作るもの | Local Position | Local Scale |
|---|---|---|---|
Body | Cube | (0, 0, 0) | (0.08, 0.08, 0.25) |
Lens | Cube | (0, 0, 0.14) | (0.06, 0.06, 0.03) |
Beam | Spot Light | (0, 0, 0.16) | (1, 1, 1) |
Beam のSpot Lightは、Rangeを 10、Spot Angleを 35、Intensityを 3、ModeをRealtimeにします。Rotationは (0, 0, 0) のままで、Z軸の方向(懐中電灯の前)を照らします。
作ったら、Beam を 無効にしておきます。消えた状態から始めます。
2. 掴めるようにする
親の Flashlight を選んで、次を追加します。
- 「Add Component」で Box Collider を追加する。Sizeを
(0.1, 0.1, 0.3)くらいにして、本体を包む大きさにする - 「Add Component」で VRC Pickup を追加する(Rigidbodyも一緒に付きます)
VRC Pickupの設定は、まずこうします。
| 項目 | 設定 |
|---|---|
| Pickupable | オン |
| Auto Hold | オン |
| Orientation | Any(あとで調整します) |
| Use Text | 点ける |
Rigidbodyは、Use Gravityをオンのまま、Is Kinematicはオフのままです。手を離したら落ちる、という自然な動きになります。
ここで一度Playしてみてください。掴んで持ち運べれば、ここまでは成功です。
3. Useで点灯するコードを書く
Assets/Scripts で「Create → U# Script」を選び、FlashlightToggle を作ります。
using UdonSharp;
using UnityEngine;
[UdonBehaviourSyncMode(BehaviourSyncMode.None)]
public class FlashlightToggle : UdonSharpBehaviour
{
[SerializeField] private Light beam;
private bool isOn;
private void Start()
{
Apply();
}
// 持っているあいだにUseを押したとき
public override void OnPickupUseDown()
{
isOn = !isOn;
Apply();
Debug.Log("[Flashlight] on=" + isOn);
}
// 手を離したときは、消しておく
public override void OnDrop()
{
isOn = false;
Apply();
}
private void Apply()
{
if (beam != null) beam.enabled = isOn;
}
}
OnPickupUseDown() は、持っているあいだにUseボタンを押したとき に呼ばれます。持っていないときは呼ばれません。
OnDrop() で消しているのは、床に落ちた懐中電灯が点きっぱなしにならないようにするためです。細かい配慮ですが、こういう後始末があると自然に見えます。
主なイベントはこの4つです。
| イベント | 呼ばれるとき |
|---|---|
OnPickup() | 掴んだ瞬間 |
OnDrop() | 手を離した瞬間 |
OnPickupUseDown() | 持っているあいだにUseを押した |
OnPickupUseUp() | そのUseを離した |
どれも、操作した本人のPCでしか呼ばれません。
4. 割り当てて確かめる
Flashlight に Udon Behaviour を追加し、FlashlightToggle を指定します。Beamに子の Beam をドラッグします。
Playして試してください。
| 操作 | 期待する結果 |
|---|---|
| 懐中電灯に近づいて掴む | 手に持て る |
| 持ったままUse(左クリック) | 光が点く。Consoleに on=True |
| もう一度Use | 消える |
| 手を離す | 床に落ちて、光も消える |
暗い部屋で試すと分かりやすくなります。Directional Lightを一時的に弱めてみてください。
握り位置を整える
持ってみると、向きが変だったり、手からずれていたりすることがあります。

VRC Pickupの Orientation で、持ち方の基準を選べます。
| 設定 | 持ち方 |
|---|---|
Any | 掴んだ位置と向きのまま持つ |
Gun | 銃のように、決まった向きで持つ |
Grip | 握るように、決まった向きで持つ |
Any は自然ですが、掴む場所によって向きが変わります。懐中電灯のように「必ずこの向きで持ってほしい」物は、Gun か Grip を使います。
Gun を選ぶと、Exact Gun という欄が出ます。ここに空のオブジェクトを指定すると、その位置と向きで持つようになります。
Flashlightの子に「Create Empty」でGripPointを作る