Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid the OnValidate method from being called in PREFAB MODE?

Tags:

unity3d

I have a gameobject as instance prefab in my scene. I have added a component that have a monobehaviour with a validation logic in OnValidate method. But I've noticed that the OnValidate method is also called when I'm in prefab mode.

So I want that some variables of an instance prefab are validated only when there are in my scene in editor mode because their values depends on other objects in the scene.

So I want to know how to avoid the OnValidate method from being called in prefab mode. Whether it is nested or not.

So I tried to write my method taking reference from here: https://github.com/Unity-Technologies/UnityCsReference/blob/master/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStageUtility.cs but it failed when the prefab is nested in another prefab.

class Helper
{
    //It doesn't work. It failed when the prefab is nested in another prefab.
    public static bool PrefabModeIsActive(Gameobject object)
    {
        UnityEditor.Experimental.SceneManagement.PrefabStage prefabStage = UnityEditor.Experimental.SceneManagement.PrefabStageUtility.GetPrefabStage (gameObject);
        if(prefabStage != null)
            return true;
        if(UnityEditor.EditorUtility.IsPersistent(gameObject))
        {
            return true;
        }

        return false;
    }
}

MyMonobehaviour

class MyMonobehaviour : MonoBehaviour
{
    public MyScriptableObject entity;

# IF UNITY_EDITOR
    void OnValidate()
    {
        //So I expected that logic onvalidate is called only on instance prefab in my scene.
        if(!Helper.PrefabModeIsActive(gameObject) && entity == null)
        {
            entity = Resources.Load<MyScriptableObject>("MyAssetScene/" + SceneManager.GetActiveScene().name) as MyScriptableObject;
        }
    }
#endif
}

So I expect that onvalidate logic is called only on instance prefab on my scene.

UPDATE 1

A alternative solution that seems to work is check some values on scene in within the gameobject:

bool PrefabModeIsActive(Gameobject gameobject)
{
    return String.IsNullOrEmpty(gameObject.scene.path)
    && !String.IsNullOrEmpty(gameObject.scene.name);
}

but I'm not sure if if there are some case studies where this might not be true

like image 869
Giuseppe Toto Avatar asked May 15 '19 17:05

Giuseppe Toto


1 Answers

You can try using PrefabStageUtility's GetCurrentPrefabStage method.

Ex.

    bool PrefabModeIsActive()
    {
        return UnityEditor.Experimental.SceneManagement.
            PrefabStageUtility.GetCurrentPrefabStage() != null;
    }
like image 63
NSJacob1 Avatar answered Nov 15 '22 10:11

NSJacob1