シリアライズ可能なクラス
CoddyのUnityジャーニー「Unityのゲームアーキテクチャ」セクションの一部。レッスン 18/64。
多くの設定を持つスクリプトは、Inspectorに長く平坦なリストを表示します。通常のC#クラスを使えば、それらをまとめられます。クラスに[System.Serializable]を付けると、そのクラス型のフィールドはフィールド名の折りたたみ項目として表示され、その中にクラスのフィールドが並びます。1つのクラスを複数のフィールドや複数のスクリプトで使えます。
[System.Serializable]
public class Stats
{
public float speed = 2f;
public int damage = 10;
}
public class Enemy : MonoBehaviour
{
public Stats normal;
public Stats enraged;
private Stats current;
void Start()
{
current = normal;
}
void Update()
{
transform.Translate(0f, 0f, current.speed * Time.deltaTime);
}
public void Enrage()
{
current = enraged;
}
}InspectorにはNormalとEnragedという2つの折りたたみ項目が表示され、それぞれにSpeedとDamageがあります。各Enemyはそれぞれ独自のStatsオブジェクトを2つ持ち、それぞれのInspectorで値を設定します。コードではnormal.speedのように値を読み取ります。Unityはスクリプトを読み込むときにこれらのオブジェクトを作成するため、= new Stats()がなくてもnormalがnullになることはありません。また、フィールド初期化子(2と10)が、新しいEnemyの初期値になります。構造体も属性を付ければ同じように使えます。[System.Serializable] public struct Range { public float min; public float max; }また、Vector3と同じく、代入時にコピーされます。
この属性が必要なのは、Unityが指示された型だけを保存するためです。属性がないと、このクラスはInspectorに表示されません。折りたたみ項目はなく、そこで設定した値も保存されず、Unityはオブジェクトも作成しないため、normal.speedはNullReferenceExceptionを発生させます。クラス内でも通常のInspectorのルールが適用されます。publicフィールド、または[SerializeField]を付けたprivateフィールドを使い、プロパティやstaticフィールドは使いません。
チャレンジ
簡単各ビームの設定を1つの構造体にまとめましょう。
Flashlightの上に、publicなColor color、float range、float angleを持つpublic struct Beamを宣言します。Inspectorに表示されるように、[System.Serializable]を付けます。- 6つの個別のフィールドを
public Beam wide;とpublic Beam focused;に置き換えます。 Apply()で、focusedOn ? focused : wideからライトの3つの値を設定します。
「プレイ」を押してSpaceキーを押すと、ビームがクリスタルに届きます。その後、「確認」を押します。
自分で試してみよう
using UnityEngine;
using UnityEngine.InputSystem;
public class Flashlight : MonoBehaviour
{
public Color wideColor = Color.white;
public float wideRange = 5f;
public float wideAngle = 60f;
public Color focusedColor = Color.white;
public float focusedRange = 10f;
public float focusedAngle = 30f;
private bool focusedOn;
private Light lamp;
void Start()
{
lamp = GetComponent<Light>();
Apply();
}
void Update()
{
if (Keyboard.current.spaceKey.wasPressedThisFrame)
{
focusedOn = !focusedOn;
Apply();
}
}
void Apply()
{
lamp.color = focusedOn ? focusedColor : wideColor;
lamp.range = focusedOn ? focusedRange : wideRange;
lamp.spotAngle = focusedOn ? focusedAngle : wideAngle;
}
}
Unityのゲームアーキテクチャのすべてのレッスン
自分で練習してみよう: Unityプレイグラウンド