UdonSharpのスクリプトを付けると、Inspectorに設定欄が出てきます。数字を入れる欄と、シーンのオブジェクトをドラッグする欄。見た目は似ていますが、この2つはまったく別のものです。
ここを分けて考えられると、コードを書き換えずに設定だけを変えられるようになります。曖昧なままだと、「コードは正しいのに動かない」に何度もぶつかります。
この記事では、値と参照の違い をつかみ、Inspectorからライトの明るさを切り替えられるようにします。
この記事でわかること
- 「値」と「参照」の違い
- コードの初期値とInspectorの値、どちらが使われるか
[SerializeField] privateを使う理由- 参照が
Noneのまま動かないときの気づき方
床のあるシーンと、最初のUdonSharp の内容を試した状態から始めます。
値はメモ、参照は指差す指
変数には2種類あります。この区別が、これから何度も効いてきます。

値 は、自分のノートに書いたメモです。「明るさ 2.0」「点灯している」「色はオレンジ」。数字や真偽をそのまま持ちます。ノートを書き換えても、ワールドの中のライトはまだ何も変わりません。
参照 は、「あのランプ」を指差す指です。指の先にある実物をいじると、ワールドの見た目が変わります。指が誰も差していなければ、どれだけノートに数字を書いても何も起きません。
VRChatの場面に置き換えると、こうなります。
スイッチのスクリプトは「明るさの数字」を持っている。でも数字だけでは部屋は明るくならない。Inspectorで どのライトを指すか を決めて、初めて押したときに照明が変わる。
もう1つ大事な性質があります。同じライトを、複数のスイッチが指せます。 入口のスイッチも非常口のスイッチも、同じ天井のライトを指していれば、どちらを押しても同じ実物が点きます。値をコピーしているのではなく、実物を共有しているからです。
この記事で使う型を並べておきます。
| 型 | 種類 | この記事での用途 |
|---|---|---|
int | 値 | 押した回数 |
float | 値 | ライトの明るさ |
bool | 値 | 明るい状態かどうか |
string | 値 | ログに出す名前 |
Color | 値 | ライトの色 |
Light | 参照 | 操作するライトそのもの |
実践:ライトの明るさを切り替える
ボタンを押すたびに、部屋のライトが暗い(0.2)と明るい(2)を行き来します。数値はコードではなくInspectorから変えられるようにします。
1. ボタンとライトを置く
床のあるシーンに、2つ置きます。
| 名前 | 作り方と設定 |
|---|---|
VariableButton | Cube。Position (0, 1, 1)、Scale (0.4, 0.4, 0.4) |
VariableLamp | Light → Point Light。Position (0, 2, 1)、Range 5、Mode「Realtime」 |

ライトのModeは Realtime にします。Bakedだと、実行中に明るさを変えても見た目が変わりません(照明とベイク で扱った話です)。
違いを見やすくするため、シーンにDirectional Lightがあれば一時的に無効にしておくと分かりやすくなります。
2. 設定を持つスクリプトを書く
Assets/Scripts で「Create → U# Script」を選び、VariableLightSwitch という名前で作ります。
using UdonSharp;
using UnityEngine;
[UdonBehaviourSyncMode(BehaviourSyncMode.None)]
public class VariableLightSwitch : UdonSharpBehaviour
{
[SerializeField] private Light targetLight; // 参照:どのライトを操作するか
[SerializeField] private float dimIntensity = 0.2f; // 値:暗いときの明るさ
[SerializeField] private float brightIntensity = 2f; // 値:明るいときの明るさ
[SerializeField] private Color lightColor = Color.white;
[SerializeField] private string logLabel = "VariableLight";
private bool isBright; // いま明るい状態か
private int pressCount; // 押された回数
private void Start()
{
if (targetLight == null)
{
Debug.LogWarning("[VariableLight] Target Lightが未設定です。");
return;
}
ApplyLight();
}
public override void Interact()
{
if (targetLight == null) return;
isBright = !isBright;
pressCount++;
ApplyLight();
Debug.Log("[" + logLabel + "] count=" + pressCount + " bright=" + isBright);
}
// 「いまの状態」を、実際のライトへ反映する
private void ApplyLight()
{
targetLight.color = lightColor;
targetLight.intensity = isBright ? brightIntensity : dimIntensity;
}
}
[SerializeField] が付いた5つがInspectorに出ます。付いていない isBright と pressCount は、実行中に内部で使うだけなので出しません。
[SerializeField] private を使う理由 があります。public にしてもInspectorには出ますが、public は「他のスクリプトからもこの変数を触ってよい」という宣言でもあります。ワールドの設定として使いたいだけなら、外から書き換えられない [SerializeField] private のほうが安全です。
ApplyLight() は、状態をライトへ反映する処理をまとめたものです。Start() と Interact() の両方から呼ぶので、1か所にまとめておくと片方だけ直し忘れる事故が防げます。
3. 参照と値を割り当てる
VariableButton に Udon Behaviour を追加し、Program Source に VariableLightSwitch を指定します。すると設定欄が出ます。
| 欄 | 指定するもの |
|---|---|
| Target Light | Hierarchyの VariableLamp |
| Dim Intensity | 0.2 |
| Bright Intensity | 2 |
| Light Color | 白 |
| Log Label | VariableLight |
| Interaction Text | 明るさを変える |
