[unity]SendMessage cannot be called during Awake, CheckConsistency, or OnValidate

インスペクタで値を変更した際、実行時だけではなくエディターでも GameObject の状態を変更したい場合があります。

using UnityEngine;

public class Test : MonoBehaviour
{
    [SerializeField]
    CanvasGroup      CanvasGroup;
    [SerializeField]
    bool             Checked;

#if UNITY_EDITOR
    void OnValidate()
    {
        CanvasGroup.blocksRaycasts = Checked;
    }
#endif
}

このコードは、Checked の値を変更すると、CanvasGroup の入力許可 / 禁止を Checked と同じ値にする、と単純なものです(警告を誘発するためのテストコードなので、実用性は置いといて)。

このコードは確かに期待通りの動きをします。が、その際 Console ウィンドウに警告を出しまくります。
今回の例のような CanvasGroup に限らず、RectTransform の値を変更…という割とやりがちなパターンでも警告は表示されてしまいます。

unity2018 のあたりかららしいですが、unity2020.3 でも発生しました。(おそらく 2021 も)

無視しても害はないのですが、あまりに大量に表示されるため困ってしまう場合は、コードを次のように書き換えると警告を出さないようになります。

パターン1

using UnityEngine;

public class Test : MonoBehaviour
{
    [SerializeField]
    CanvasGroup      CanvasGroup;
    [SerializeField]
    bool             Checked;

#if UNITY_EDITOR
    private void OnValidate()
    {
        UnityEditor.EditorApplication.delayCall += _OnValidate;
    }
 
    private void _OnValidate()
    {
        UnityEditor.EditorApplication.delayCall -= _OnValidate;
        if(this == null) return;
        CanvasGroup.blocksRaycasts = Checked;
    }
#endif
}

パターン2

[ExecuteInEditMode]
public class Test : Monobehaviour
{
    [SerializeField]
    CanvasGroup      CanvasGroup;
    [SerializeField]
    bool             Checked;

    bool             changed;
 
#if UNITY_EDITOR
    private void OnValidate()
    {
        changed = true;
    }
#endif
 
    private void LateUpdate()
    {
        if (changed)
        {
            CanvasGroup.blocksRaycasts = Checked;
            changed = false;
        }
    }

おすすめはパターン1

パターン1は記述の変更も少なく、負荷もそのままなのでオススメです。
パターン2はエディタでも常に Update を実行してしまうのと、いちいちフラグ管理を強要されるのがマイナス点。

返信を残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA