ScriptableObject
のAwake
とOnEnable
はMonoBehaviour
のAwake
とOnEnable
とでまったく異なるタイミングで走るのでまずその説明をさせてください。
MonoBehaviourとScriptableObject イベント関数の違い
ヒエラルキーに設置しているオブジェクト(MonoBehaviour
)とアタッチしているScriptableObject
はゲーム(ランタイム)開始時に自動的に生成されると思ってください。
▼ MonoBehaviour
[Awake
] ゲーム(ランタイム)中に生成された時1度だけ走る
[OnEnable
] ゲーム(ランタイム)中に表示された時毎回走る(生成時やSetActive(true)した時)
▼ ScriptableObject
[Awake
] 生成された時走る(クラスに[CreateAssetMenu]
アトリビュートをアタッチし右クリック > Create > スクリプト名で生成する時や既に存在するScriptableObject
を複製した時スクリプトを修正した時)
[OnEnable
] ゲーム(ランタイム)中初めて読み込まれた時に1度だけ走る
ScriptableObject
のAwake
のみランタイムは関係ありません。
生成後Project上に残り続けるデータだからです。メソッド名が同じなので混乱しますね。違う名前にして欲しかったです。
###今回の用件に合いそうなのはScriptableObject.OnEnable()
Awake()
をOnEnable()
に書き換えれば求める挙動になります。1つ訂正する点があるとすればpower
がScriptableObject
に書き込まれてしまうので下記のようにすると良いです。
C#
1using System;
2using UnityEngine;
3
4// 右クリックでScriptableObjectを生成できるようにする
5[CreateAssetMenu(menuName = "ScriptableObject/Data")]
6public class Data : ScriptableObject
7{
8 public string name;
9 public int HP;
10
11 // この変数は保存されないようにアトリビュートを追加
12 [NonSerialized] public int power;
13
14 public void OnEnable()
15 {
16 power = HP / 10;
17 Debug.Log("awake");
18 }
19}
イベントの実行順
ヒエラルキーに設置したオブジェクト(MonoBehaviour
)とアタッチしているScriptableObject
と想定すると下記の実行順となります。
- ScriptableObject.OnEnable()
- MonoBehaviour.Awake()
- MonoBehaviour.OnEnable()
- MonoBehaviour.Start()
今回詳しく解説した理由
今回のpower
は取得タイミングによって値が変わります。
OnEnable
が走る前は0を返し、OnEnable
が走った後は計算された値を返します。
こういうのをプログラム用語で「副作用がある」と言います。
今回の説明でOnEnable
でpower
に代入すれば常に計算された値を取得できる事が保証されているのが分かると思います。
特に今回のような戻り値のあるもので副作用がある場合、バグになりやすいので徹底的に問題無いか調査するのをおすすめします。