0
\$\begingroup\$

Why does calling gameObject.SetActive()(in the Editor) take quite noticeable time (in my case about 8 secs) if a game object has some significant number of children, while changing the state of the same object using its checkbox in the Inspector panel looks instantaneous?

I always thought that the checkbox enter image description here

and the SetActive method do the same job for the object. Don't they?

Test code:

[DisallowMultipleComponent]
public class GameObjectState : MonoBehaviour
{
    public bool active;

    private void OnValidate()
    {
        gameObject.SetActive(active);
    }

    private void Reset()
    {
        active = gameObject.activeSelf;
    }
}
\$\endgroup\$
2
  • \$\begingroup\$ I've never seen a call to SetActive take 8 seconds! Can you edit your question to walk us through the steps to build a Minimal Complete Verifiable Example? Starting from an empty project, what would we need to add to our scene to reproduce this problem? Once we can reproduce it, we can test potential solutions to be sure they will work for you. \$\endgroup\$
    – DMGregory
    Jun 19, 2021 at 12:02
  • \$\begingroup\$ Let us continue this discussion in chat. \$\endgroup\$
    – DMGregory
    Jun 19, 2021 at 12:32

1 Answer 1

0
\$\begingroup\$

As DMGregory pointed in the discussion my GameObjectState component was causing many warnings of this type:

SendMessage cannot be called during Awake, CheckConsistency, or OnValidate

As a consequence, excessive logging led to the editor freezing when toggling the checkbox.

While the reason for this warning is not completely clear to me, it is obvious that it was caused by calling gameObject.SetActive from the OnValidate method.

A possible workaround for safely calling gameObject.SetActive could be to use a custom editor:

[CustomEditor(typeof(GameObjectState))]
public class GameObjectStateEditor : Editor
{
    private GameObjectState _target;
    private bool _wasActive;

    private void OnEnable()
    {
        _target = (GameObjectState)target;
        _wasActive = _target.active;
    }

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        if (_wasActive == _target.active)
            return;

        _target.gameObject.SetActive(_target.active);
        _wasActive = _target.active;
    }
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .