Update はフレームごとに実行されますが、メソッド内で宣言した変数はフレームをまたいで保持されません。フレーム間でデータを持ち続けるにはフィールドを使います。
このページを読み終えると、以下のことができるようになります。
[SerializeField] を使って Inspector からフィールドの値を編集できるUpdate 内で変数を宣言すると、その変数はそのフレームの中だけで有効で、次のフレームでは消えてしまいます。たとえばカウンターを作ろうとして次のように書いても、意図した動作にはなりません。
1
2
3
4
5
6
7
8
9
10
11
using UnityEngine;
public class FieldSample : MonoBehaviour
{
private void Update()
{
var count = 0; // 毎フレーム 0 にリセットされる
count++;
Debug.Log(count); // 常に 1 と出力される
}
}
count は毎フレーム 0 で初期化されるため、値が積み上がりません。
クラス内・メソッドの外に変数を宣言すると、インスタンスが生きている間ずっとデータを保持できます。このような変数をフィールドと呼びます。
書式:フィールドの宣言
1
アクセス修飾子 型 フィールド名 = 初期値;
| 要素 | 説明 |
|---|---|
アクセス修飾子 |
private(クラス内のみ)や public(外部からも参照可)など |
型 |
int・float・string など |
フィールド名 |
変数の名前 |
= 初期値 |
省略可。省略した場合はデフォルト値(数値なら 0)が入る |
💡 ポイント: アクセス修飾子や型の詳細は C# 基礎 のセクションで改めて学びます。ここでは「クラスの中、メソッドの外に書くとフレームをまたいで保持される」と覚えておきましょう。
フィールドを使ってカウンターを書き直すと、正しく動作します。
1
2
3
4
5
6
7
8
9
10
11
12
using UnityEngine;
public class FieldSample : MonoBehaviour
{
private int _count = 0; // フィールド: フレームをまたいで保持される
private void Update()
{
_count++;
Debug.Log(_count); // 1, 2, 3 … と増えていく
}
}
💡 ポイント:
privateフィールドにはアンダースコア_を先頭に付ける命名慣習があります(_count・_speedなど)。メソッド内のローカル変数(var count)との区別が一目でつき、コードが読みやすくなります。
前のページで書いた移動コードに登場した 5.0f はハードコードされた数値です。速度を変えるたびにコード内を検索して書き直す必要があります。
1
2
3
// ❌ NG: 速度が複数箇所にハードコードされていて管理しにくい
transform.Translate(Vector3.right * 5.0f * Time.deltaTime);
transform.Translate(Vector3.left * 5.0f * Time.deltaTime);
この数値をフィールドに切り出すと、1か所を変えるだけで全体に反映されます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// ✅ OK: 速度をフィールドで管理する
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerMover : MonoBehaviour
{
private float _speed = 5.0f; // 速度をフィールドで管理
private void Update()
{
if (Keyboard.current.rightArrowKey.isPressed)
{
transform.Translate(Vector3.right * _speed * Time.deltaTime);
}
if (Keyboard.current.leftArrowKey.isPressed)
{
transform.Translate(Vector3.left * _speed * Time.deltaTime);
}
}
}
private フィールドはクラスの外部からアクセスできませんが、[SerializeField] 属性を付けると、コードを書き直さずに Unity の Inspector ビューから値を編集できるようになります。
[SerializeField] — private フィールドを Inspector に表示して編集できるようにします。
書式:SerializeField 属性
1
[SerializeField] アクセス修飾子 型 フィールド名 = 初期値;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerMover : MonoBehaviour
{
[SerializeField] private float _speed = 5.0f;
private void Update()
{
if (Keyboard.current.rightArrowKey.isPressed)
{
transform.Translate(Vector3.right * _speed * Time.deltaTime);
}
if (Keyboard.current.leftArrowKey.isPressed)
{
transform.Translate(Vector3.left * _speed * Time.deltaTime);
}
}
}
Inspector ビューの Script コンポーネントに Speed フィールドが表示され、コードを変更せずに速度を調整できます。Play 中に値を変えてリアルタイムに挙動を確認することもできます。
💡 ポイント:
publicにしても Inspector に表示されますが、[SerializeField] privateにすることで「外部からは参照できないが、Inspector からは編集できる」という適切なカプセル化が保たれます。
[SerializeField] を付けると private を保ちながら Inspector から値を編集できる以下の問いに答えられるか確認しましょう。
Update 内でカウンターを作りたいのに、値が毎フレーム 1 になってしまいます。原因は何ですか?[SerializeField] を付けるメリットを2つ答えてください。次のコードの _speed フィールドを Inspector から編集できるように修正してください。
1
private float _speed = 3.0f;
Update メソッド内(ローカル変数)で宣言されているため、毎フレーム 0 に初期化されている。フィールドとしてクラスレベルで宣言する必要がある。private を保ちながら外部編集できるためカプセル化が崩れない。1
[SerializeField] private float _speed = 3.0f;