データアセット
CoddyのUnityジャーニー「Unityのゲームアーキテクチャ」セクションの一部。レッスン 23/64。
農場ゲームでニンジンとカボチャを育てます。ニンジンは30秒で育ち、5コインで売れます。カボチャは90秒で育ち、40コインで売れます。これらの数値は作物に属するもので、個々の植物に属するものではありません。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は使いません。
チャレンジ
中級ヒーローの設定をデータアセットに移しましょう。
HeroData.csに、publicstring heroName、float moveSpeed、Color colorを持つpublic class HeroData : ScriptableObjectを書きます。- その1行上に
[CreateAssetMenu(menuName = "Heroes/Hero Data")]を記述します。 Hero.csで、3つのフィールドをpublic HeroData data;に置き換え、代わりにdata.heroName、data.moveSpeed、data.colorを読み取ります。
「プレイ」を押します。赤いナイトが速度3で歩きます。その後、「確認」を押します。
自分で試してみよう
using UnityEngine;
// HeroData: ヒーローの名前、速度、色を保持するScriptableObject
Unityのゲームアーキテクチャのすべてのレッスン
自分で練習してみよう: Unityプレイグラウンド