Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

In Unity 2018.2.6f1, trying to set sizeDelta in inspector using OnValidate() throws warning.

Discussion in 'Editor & General Support' started by fogsight, Sep 4, 2018.

  1. fogsight

    fogsight

    Joined:
    Apr 6, 2010
    Posts:
    65
    Warning message "SendMessage cannot be called during Awake, CheckConsistency, or OnValidate"

    Code (CSharp):
    1.     public Vector2 sizeDelta = Vector2.zero;
    2.  
    3.     private void OnValidate() {
    4.         GetComponent<RectTransform>().sizeDelta = sizeDelta;
    5.     }
    Actual use case is using OnValidate inside Scriptable Object, but result is the same.
    Also default Slider component throws the same warning when trying to change slider value through inspector.
     
    Rond likes this.
  2. Rond

    Rond

    Joined:
    Oct 21, 2009
    Posts:
    175
    Up,

    Same here.
     
  3. PandaArcade

    PandaArcade

    Joined:
    Jan 2, 2017
    Posts:
    128
    Still the same in 2019.1.4f1

    Although the slider component does not throw the warning.

    Unity should I be concerned?
     
  4. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    No, that warning for OnValidate is completely meaningless.

    I guess UT wasn't bothered to add a check for the SendMessage and OnValidate calls.
    As SendMessage should simply be ignored while Application is not playing.

    Or doesn't exist at all, because SendMessage is an abomination.
     
  5. ErikH2000

    ErikH2000

    Joined:
    Apr 30, 2014
    Posts:
    13
    Spent some time this year ignoring the "SendMessage" warning, and I now think that it *does* matter. Calls to certain Unity APIs fail intermittently when made from OnValidate(). I recommend using OnValidate() to set a flag that is read in Update(), and then you perform any scene modification inside of Update()--not in OnValidate(). The warnings go away. The intermittent failures go away. I wrote a longer article with details about the issue here, including example code: https://medium.com/@ErikH2000/tips-for-procedural-generation-in-the-unity-editor-for-decorating-scenes-b714fd0daa9c
     
  6. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    Its a specific case about .SetParent() in which it does matter.
    Although I highly doubt UT using SendMessage to notify transforms.
    Its probably used for UI components notification. We may never know.

    However, I think .Update() is an overkill.
    EditorApplication.delayCall might be a better callback for this one.
    But maybe it doesn't mater for the editor time, and easier to implement.
     
    Last edited: Jun 30, 2019
  7. ErikH2000

    ErikH2000

    Joined:
    Apr 30, 2014
    Posts:
    13
    delayCall() would work for me, but in my delayCall() code I would sometimes get console errors about an object instance being invalid. I can't remember if it was going from edit to play mode or visa-versa (probably the former), but it seems like you lose control of where in the life cycle delayCall() will be made, so it may get called at a time when things are unloaded. Agree that putting the scene-modifying code in Update() is a pain and maybe unneeded. But I want a clean console log.
     
  8. fogsight

    fogsight

    Joined:
    Apr 6, 2010
    Posts:
    65
    This problem/annoyance is still around, it seems. I'll add another maybe slightly more palatable solution using editor coroutines. All you need is to wait for the end of the frame or skip the first frame entirely, and it runs without "SendMessage" log warning.

    Code (CSharp):
    1.     private void OnValidate() {
    2.         StartCoroutine(RunSizeDeltaUpdate());
    3.     }
    4.  
    5.     private IEnumerator RunSizeDeltaUpdate() {
    6.         //yield return new WaitForEndOfFrame(); //Edit: WaitForEndOfFrame causes weirdness sometimes with UI update, just skipping frame works better.
    7.         yield return null;
    8.         GetComponent<RectTransform>().sizeDelta = sizeDelta;
    9.     }
    Without it message otherwise triggers.
     
    Last edited: Jun 28, 2020
    PandaArcade likes this.
  9. Smack332

    Smack332

    Joined:
    Nov 5, 2018
    Posts:
    9
    Thank you, that removed the warning. However, for me it introduced an error stating the coroutine couldn't be started because the game object was inactive. To get rid of this, I altered the code as follows:

    Code (CSharp):
    1.     private void OnValidate() {
    2.         if (gameObject.activeInHierarchy)
    3.             StartCoroutine(RunSizeDeltaUpdate());
    4.     }
    5.     private IEnumerator RunSizeDeltaUpdate() {
    6.         yield return null;
    7.         GetComponent<RectTransform>().sizeDelta = sizeDelta;
    8.     }