データアセット
CoddyのUnityジャーニー「Unityにおけるゲームアーキテクチャ」セクションの一部。レッスン 19/50。
農場ゲームでニンジンとカボチャを育てます。ニンジンは30秒で育ち、5コインで売れます。カボチャは90秒で育ち、40コインで売れます。これらの数値は植物1つではなく、作物に属します。PlantスクリプトのInspectorフィールドとして設定すると、すべてのシーンにあるニンジンがそれぞれ30と5のコピーを持つことになり、変更するにはそのすべてを探さなければなりません。ScriptableObjectを使うと、このようなデータをアセット(プロジェクト内のファイル)に保存し、いくつものオブジェクトから参照できます。そのクラスはMonoBehaviourではなくScriptableObjectを継承します。
using UnityEngine;
[CreateAssetMenu(fileName = "NewPlant", menuName = "Farm/Plant Data")]
public class PlantData : ScriptableObject
{
public string plantName;
public float growTime;
public int sellPrice;
}[CreateAssetMenu]を付けると、ProjectウィンドウのCreateメニューにこのクラスが追加されます。Projectウィンドウを右クリックし、Create > Farm > Plant Dataを選ぶと、UnityがNewPlantという名前のアセットを作成します。名前をCarrotに変更して選択し、InspectorのフィールドにCarrot、30、5と入力します。Pumpkinアセットも同じ方法で作成します。MonoBehaviourと同様に、クラスはその名前を付けたPlantData.csというファイルに記述します。
動作は、アセットの型のフィールドを持つMonoBehaviourに記述します。Carrotアセットをそのフィールドにドラッグすると、スクリプトはそこから数値を読み取ります。
public class Plant : MonoBehaviour
{
public PlantData data;
private float age;
void Update()
{
age += Time.deltaTime;
if (age >= data.growTime)
{
Debug.Log(data.plantName + " is ready, worth " + data.sellPrice);
enabled = false;
}
}
}ScriptableObjectはGameObjectにもシーンにも属しません。Transformを持たず、UnityがそのUpdateやStartを呼び出すこともありません。データを保持するのはScriptableObjectで、動作を保持するのはPlantです。200個のニンジンが1つのCarrotアセットを参照している場合、そのgrowTimeを25に設定すると、200個すべてに変更が反映されます。コードでインスタンスを作るにはScriptableObject.CreateInstance<PlantData>()を使い、newは使いません。
チャレンジ
中級Heroは矢印キーでアリーナを歩き回ります。名前、速度、色はHeroスクリプトのフィールドで、新しいHeroを作るたびにそれらをもう一度コピーする必要があります。これらをアセットに移しましょう。
HeroData.csで、publicフィールドheroName(string)、moveSpeed(float)、color(Color)を持つScriptableObject、HeroDataを記述します。メニュー名Heroes/Hero Dataで[CreateAssetMenu]を付けます。Hero.csで、3つのフィールドをHeroData型のpublicフィールドdata1つに置き換え、スクリプト自身の値を使っていた箇所でアセットの値を使います。
プロジェクトには、そのメニューで作成されたKnightアセット(Knight、速度3、赤)があり、InspectorでそれがHeroのdataフィールドに設定されています。再生を押してKnightを歩き回らせてから、確認を押してください。
自分で試してみよう
using UnityEngine;
// HeroData: ヒーローの名前、速度、色を保持するScriptableObject
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。