スクリプトの初期値が反映されない? それ、Inspectorのせいかもしれません
Unityで開発していて、変数の初期値をコードで設定したのになぜか反映されない!
「ちゃんと int i = 100; って設定してるのに…」となったことはありますか?
私はたまに忘れた頃にやらかして、数分〜10分程度を無駄にすることが何度かありますw
結論から言うと、これは Inspectorにすでに保存された値が優先される という、Unity特有の仕様が原因です。
しかもこの仕様、一度でもInspector上で値が設定された変数は、コードの変更を無視するという仕組みなんです。
そう!これはUnityの仕様!たまに忘れる私が悪い!w
なにが起きてるのか?
たとえばこんなコードを書いたとします。
public class TestEnemy : MonoBehaviour
{
public int hp = 100;
}
この状態で TestEnemy
をアタッチした GameObject を作ると、Inspectorには「hp = 100」と表示されます。
さて、この後スクリプトを変更して、hpの初期値を 200
に変えてみます。
public int hp = 200; // ←ここを変更!
だがしかし!
ゲーム実行時も、Inspector上でも、hpは「100」のまま。
Unityの「シリアライズ優先」の仕様
Unityは、一度でもInspector上で変数が保存されると、コード上の初期値を無視してInspector側の値を使い続ける仕様になっています。
つまり、
public
または [SerializeField]
付き変数
→ 初めてInspectorに表示された時点で、その値が「保存」される
→ 以後、スクリプトの初期値を変更してもInspectorには反映されない
コードで hp = 200
にしても、Inspectorが「100」を覚えてるからそっちが使われるんですね。
=Inspectorが勝つ ということです。
解決方法:リセットする or 設計を変える
方法①:Resetを使う
GameObjectを選択して右クリック → Reset
を押すと、Inspectorに保存された値がリセットされ、コード上の初期値が反映されます。
ただし、他の変数まで全部初期化されてしまうので注意。
方法②:Inspectorの値を直接変更する
手動で値を変えればOKですが、意図せず「コードと違う値」が残り続ける危険があります。
方法③:初期値の管理を Awake() や Start() に寄せる
例えばこんなふうにします:
csharpコピーする編集する[SerializeField]
private int hp;
void Awake()
{
if (hp == 0) hp = 200;
}
このように 初期化をコードで強制する方法もあります。
ただし「本当に0の可能性がある値」は注意が必要(boolやfloatなど)。
方法④ : そもそもInspectorに表示させない(変更方法を統一する)
public や SerializeField を使わず、コードだけで設定するようにする。
どうしてもpublicにしないといけない設計なら、[HideInspector]などで非表示にしちゃう。
もしくは逆に Inspectorの設定のみにして、コードの変数初期化は使わない、と決めてしまう。
どちらかに統一されてれば間違う可能性は下がりますね。
私は方法④のコードのみの設定になることが多いです。
そもそも外に出さない作りにしちゃえば、こんな問題遭遇することはないんですよ…!←
まとめ
個人的にこの「Unityあるある」は開発時に遭遇してイラつくことNo.1です。
(え?遭遇しますよね?私だけ?)
デフォルト値を変えたのに動かない
→ デバッグに時間を使う
→ よく見たらInspectorに前の値が残ってるじゃねぇか!
ってので時間を無駄にするのが本当に嫌いです。
初心者のこと引っ掛かってた系で言うと、「シーン再生時、再生していることを忘れてInspector変更→変更内容が消える」もあるあるかな…
もし何か他にもあるある系のネタをお持ちであれば、ぜひ教えてくださいw
コメント