部屋に3つのライトを置いて、順番に点けたい。素直に書くと、こうなります。
[SerializeField] private Light light1;
[SerializeField] private Light light2;
[SerializeField] private Light light3;
動きます。でも5個に増やすと5行、10個なら10行です。しかも処理のほうも同じだけコピーすることになり、直すときは全部を直す羽目になります。
この記事では、同じ種類のものをまとめて扱う配列 を使って、3灯のライトを1つのコードで切り替えます。
この記事でわかること
- 配列でまとめると何が楽になるか
- 添字が0から始まる理由
- 範囲外アクセスを防ぐ書き方
- Inspectorで要素が空のときに起きること
変数と参照 を試した状態から始めます。
配列は、仕切りのあるトレイ
配列は、同じ種類のものを、番号を付けて並べて入れる箱 です。

変数を3つ別々に書くと、それぞれ独立した箱です。名前で呼び分けるしかありません。
配列にすると、仕切りのある1つのトレイになります。番号で選べる ので、「3番目のライト」という指定ができます。ここが決定的に違います。
書き方はこうです。
[SerializeField] private Light[] lights; // Lightの配列
// 使うとき
lights[0].enabled = true; // 1つ目
lights[1].enabled = true; // 2つ目
Light[] の [] が「配列である」という印です。lights[0] の [0] が 添字(そえじ) で、何番目かを指します。
添字は0から始まります。 3個の配列なら 0 1 2 です。3 は存在しません。
最初は違和感がありますが、理由があります。添字は「先頭から何個ぶんずれた場所か」を表しています。先頭は0個ずれているので0番、その次が1番です。
配列が便利なのは、番号を変数にできる こ とです。
int index = 2;
lights[index].enabled = true; // 3つ目が点く
これができると、for で全部を順に処理したり、押すたびに次のライトへ進めたりできます。変数を3つ並べていたら、こうはいきません。
実践:3灯を順番に切り替える
ボタンを押すたびに、点灯するライトが左から右へ移っていきます。3つ目の次は最初に戻ります。
1. ライト3つとボタンを置く
床のあるシーンに4つ置きます。
| 名前 | 作り方と設定 |
|---|---|
Lamp0 | Point Light。(-1.5, 2.2, 1)、Range 4、Intensity 2、Mode「Realtime」 |
Lamp1 | Point Light。(0, 2.2, 1)、同上 |
Lamp2 | Point Light。(1.5, 2.2, 1)、同上 |
LampButton | Cube。(0, 1, -1)、Scale (0.4, 0.4, 0.4) |

名前を Lamp0 から始めているのは 、添字と対応させて混乱を減らすためです。
2. コードを書く
Assets/Scripts で「Create → U# Script」を選び、LampSequence を作ります。
using UdonSharp;
using UnityEngine;
[UdonBehaviourSyncMode(BehaviourSyncMode.None)]
public class LampSequence : UdonSharpBehaviour
{
[SerializeField] private Light[] lamps; // 3つのライトをまとめて受け取る
private int currentIndex;
private void Start()
{
Apply();
}
public override void Interact()
{
// 次へ進める。最後まで行ったら0へ戻す
currentIndex++;
if (currentIndex >= lamps.Length)
{
currentIndex = 0;
}
Apply();
Debug.Log("[LampSequence] index=" + currentIndex);
}
// 今の番号のライトだけを点ける
private void Apply()
{
for (int i = 0; i < lamps.Length; i++)
{
if (lamps[i] == null) continue; // 空の欄は飛ばす
lamps[i].enabled = (i == currentIndex);
}
}
}
見どころが3つあります。
lamps.Length を使っています。 配列の要素数を返すプロパティです。3 と直接書くと、ライトを4つに増やしたときにコードも直す必要があります。Length なら、Inspectorで増やすだけで対応できます。
for で全部を回しています。 i が0から Length - 1 まで動きます。i < lamps.Length であって i <= lamps.Length ではないことに注意してください。ここを間違えると、次の節の範囲外アクセスになります。

lamps[i].enabled = (i == currentIndex); の1行で、点けると消すを同時にやっています。「いまの番号と同じなら true、違えば false」という意味です。全部の要素に対して実行するので、前に点いていたものは自動的に消えます。
3. Inspectorで割り当てる
LampButton に Udon Behaviour を追加し、LampSequence を指定します。
Inspectorに Lamps という欄が現れます。配列なので、まずサイズを決めます。
- Lamps を開いて、Size に
3と入力する Element 0にLamp0をドラッグするElement 1にLamp1、Element 2にLamp2をドラッグする
サイズを増やす と、空の欄(None)が現れます。 必ず全部埋めてください。埋め忘れると、次の節の事故が起きます。
Interaction Text は 次のライト にします。
4. 動かして確かめる
Playして、ボタンを押してみてください。
| 操作 | 期待する結果 |
|---|---|
| 開始直後 | 左のライトだけが点いている。index=0 |
| 1回押す | 真ん中に移る。index=1 |
| 2回押す | 右に移る。index=2 |
| 3回押す | 左に戻る。index=0 |
ライトを4つに増やしてみてください。 Lamp3 を作り、InspectorでSizeを 4 にして割り当てるだけです。コードは1文字も変えていないのに、4つを順に回るようになります。
これが配列の効果です。
範囲外に手を伸ばさない
配列でいちばん多い失敗が、存在しない番号を指すこと です。
Light[] lamps = new Light[3]; // 0, 1, 2 の3つ
lamps[3].enabled = true; // 3は存在しない
3個の配列に 3 はありません。実行すると エラーが出て、そこで処理が止まります。 その先のコードは動きません。
