グラフィカルなボタンをデザインして、その表示内容をスクリプトで切り替えたい場合があります。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ButtonTextSelector : MonoBehaviour
{
public Sprite[] Jp;
public Sprite[] En;
public enum TxtList
{
Tutorial, Option, GameStart, OK, Tweet, Title, Skip, Close
}
public bool isJp = true;
[SerializeField]
private TxtList _Txt = TxtList.OK;
public TxtList Txt
{
set
{
_Txt = value;
int idx = (int)Txt;
if (isJp)
{
GetComponent<SpriteRenderer>().sprite = Jp[idx];
}
else
{
GetComponent<SpriteRenderer>().sprite = En[idx];
}
}
get { return _Txt; }
}
}
ですが、このままでは実行するまで表示内容がかわらないため、インスペクターで設定した値で表示内容を確認したい場合、
void OnValidate()
{
Txt = Txt;
}
のようにOnValidate()をつけてインスペクターの値が変更されたときの処理を書くことが多いと思いますが、このOnValidate()を使ってインスペクターの値を変更すると、
と一応は反映されますが、"SendMessage cannot be called during Awake, CheckConsistency, or OnValidate UnityEngine.StackTraceUtility:ExtractStackTrace ()"という警告が出ます。
しかも#pragma warning disable XXX で表示を消すことが出来ず、非常にうざったらしいです。
なのでこの警告を出さずにインスペクターの値を反映させるためには、クラスの頭に[ExecuteAlways]アトリビュートをつけて、Update()で更新させるようにします。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[ExecuteAlways]
public class ButtonTextSelector : MonoBehaviour
{
public Sprite[] Jp;
public Sprite[] En;
public enum TxtList
{
Tutorial, Option, GameStart, OK, Tweet, Title, Skip, Close
}
public bool isJp = true;
[SerializeField]
private TxtList _Txt = TxtList.OK;
public TxtList Txt
{
set
{
_Txt = value;
int idx = (int)Txt;
if (isJp)
{
GetComponent<SpriteRenderer>().sprite = Jp[idx];
}
else
{
GetComponent<SpriteRenderer>().sprite = En[idx];
}
}
get { return _Txt; }
}
void Update()
{
if (!Application.isPlaying)
{
Txt = Txt;
}
}
}
[ExecuteAlways]をつけるとエディター上でも実行中と同じ処理を行うようになるため、Update()が実際に実行されインスペクターの値が反映されるという仕組みです。
"SendMessage cannot be called during Awake"の警告が出なくなりました。