如何避免在PREFAB MODE中调用OnValidate方法?

时间:2019-05-15 17:56:42

标签: unity3d

我的场景中有一个游戏对象作为预制实例。我在OnValidate方法中添加了具有验证行为逻辑的单一行为的组件。但是我注意到,当我处于预制模式时,也会调用OnValidate方法。

所以我希望实例预制的某些变量仅在我的场景中处于编辑模式时才被验证,因为它们的值取决于场景中的其他对象。

所以我想知道如何避免在预制模式下调用OnValidate方法。是否嵌套。

因此,我尝试编写从此处引用的方法:https://github.com/Unity-Technologies/UnityCsReference/blob/master/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStageUtility.cs,但是当预制件嵌套在另一个预制件中时,该方法将失败。

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;
        }
    }
}

我的Monobe行为

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
}

因此,我希望onvalidate逻辑仅在场景中的实例预制上调用。

更新1

一种可行的替代解决方案是检查游戏对象中场景中的某些值:

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

但是我不确定是否有一些案例研究可能不正确

2 个答案:

答案 0 :(得分:0)

您可以尝试使用PrefabStageUtility's GetCurrentPrefabStage方法。

例如。

    bool PrefabModeIsActive()
    {
        return UnityEditor.Experimental.SceneManagement.
            PrefabStageUtility.GetCurrentPrefabStage() != null;
    }

答案 1 :(得分:0)

在我的所有项目中都使用了以下几行代码,以避免出现这种令人讨厌的功能。

#if UNITY_EDITOR
using UnityEditor.Experimental.SceneManagement;
using UnityEditor;
#endif

void OnValidate()
    {
#if UNITY_EDITOR
        PrefabStage prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
        bool isValidPrefabStage = prefabStage != null && prefabStage.stageHandle.IsValid();
        bool prefabConnected = PrefabUtility.GetPrefabInstanceStatus(this.gameObject) == PrefabInstanceStatus.Connected;
        if (!isValidPrefabStage && prefabConnected)
        {
            //Variables you only want checked when in a Scene
        }
#endif
        //variables you want checked all the time (even in prefab mode)
   }

这有两件事。第一,它在预制模式下不会检查变量,在预制模式有效之前也不会检查变量。您不会看到的第二个好处很多,但是有时当您打开一个新项目或删除您的库文件夹并需要重新导入资产时,您会在Preab有效之前触发OnValidate(),甚至只放置“ isPrefabConnected”无法正常工作。