龙空技术网

NGUI5.6与Unity2018.3 PrefabMode冲突问题解决方案

博毅创为游戏圈 58

前言:

今天咱们对“unity怎么把场景转为prefab”大体比较注意,朋友们都想要分析一些“unity怎么把场景转为prefab”的相关文章。那么小编在网摘上搜集了一些关于“unity怎么把场景转为prefab””的相关知识,希望兄弟们能喜欢,咱们快快来了解一下吧!

情景:

Unity在升级到2018.3版本后 新增了Prefab Mode系统,可以通过Open Prefab直接打开新的Scene对预设进行编辑。

NGUI的UI控件需要依附于UIRoot节点作为其顶级父节点,UIRoot主要是控制UI控件的变化和缩放。

问题:

Unity的Prefab Mode强制在对Prefab节点进行删除/移动时 需要在Prefab Mode系统中才能进行,因此若是在NGUI5.6升级Unity到2018.3 就会出现 在Scene场景中无法删、移预设,但是进入Prefab Mode会有导致NGUI控件报错的问题。

解决方法:

1,简单的解决方法是 每次进行预设编辑时 使用Unpack 进行预设的解引用,这样不需要进入Prefab Mode也可以进行预设的删、移,而缺点就是 每次修改之后需要进行预设的覆盖,带来操作成本,隐患则是进行Unpack会导致引用丢失,需要每次都重新拖引用,提高了操作失误率。

2,对NGUI 5.6 源码修改,在进入Prefab Mode时为其创建UIRoot,在寻找解决方案的时候发现了NGUI2018已经有相应的解决方法,这里将需要修改的代码整理出来:

1,实现配置环境

UIRect.cs `protected virtual void Awake () {  ``#if UNITY_2018_3_OR_NEWER ``    NGUITools.CheckForPrefabStage (gameObject);  ``#endif ``    mStarted = false; ``    mGo = gameObject; ``    mTrans = transform; ``} ``static public void CheckForPrefabStage (GameObject gameObject) {  ``#if UNITY_EDITOR && UNITY_2018_3_OR_NEWER ``    var prefabStage = UnityEditor.Experimental.SceneManagement.PrefabStageUtility.GetPrefabStage (gameObject); ``    if (prefabStage == null) ``        return; ``    var rootsInParents = gameObject.GetComponentsInParent<UIRoot> (true); ``    var panelsInParents = gameObject.GetComponentsInParent<UIPanel> (true); ``    bool missingRoot = rootsInParents.Length == 0; ``    bool missingPanel = panelsInParents.Length == 0; ``    if (!missingRoot && !missingPanel) ``        return; ``    // Since this function is called from Awake/OnEnable, utilities like PrefabStage.prefabContentsRoot ``    // or Scene.GetRootGameObjects () aren't available at this point ``    var instanceRoot = gameObject.transform; ``    while (instanceRoot.parent != null) ``        instanceRoot = instanceRoot.parent; ``    GameObject container = UnityEditor.EditorUtility.CreateGameObjectWithHideFlags ("UIRoot (Environment)", HideFlags.DontSave); ``    container.layer = instanceRoot.gameObject.layer; ``    if (missingRoot) ``        container.AddComponent<UIRoot> (); ``    if (missingPanel) ``        container.AddComponent<UIPanel> (); ``    UnityEngine.SceneManagement.SceneManager.MoveGameObjectToScene (container, prefabStage.scene); ``    instanceRoot.SetParent (container.transform, false); ``#endif ``} `

2,实现在预设场景能够正确保存NGUI预设

NGUITools.cs `static public void SetDirty (UnityEngine.Object obj) ``{  ``#if UNITY_EDITOR ``    if (obj) ``    {  ``        if (UnityEditor.AssetDatabase.Contains(obj)) ``        {  ``            UnityEditor.EditorUtility.SetDirty(obj); ``         } ``        else if (!Application.isPlaying) ``        {  ``            if (obj is Component) ``            {  ``                var component = (Component)obj; ``                UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(component.gameObject.scene); ``             } ``            else if (obj is UnityEditor.EditorWindow || obj is ScriptableObject) ``            {  ``                UnityEditor.EditorUtility.SetDirty(obj); ``             } ``            else ``            {  ``                UnityEditor.EditorUtility.SetDirty(obj); ``                UnityEditor.SceneManagement.EditorSceneManager.MarkAllScenesDirty(); ``             } ``         } ``     } ``    //if (obj) ``    //{  ``    // //if (obj is Component) Debug.Log(NGUITools.GetHierarchy((obj as Component).gameObject), obj); ``    // //else if (obj is GameObject) Debug.Log(NGUITools.GetHierarchy(obj as GameObject), obj); ``    // //else Debug.Log("Hmm... " + obj.GetType(), obj); ``    // UnityEditor.EditorUtility.SetDirty(obj); ``    // } ``#endif ``} `

3,实现渲染

UIDrawCall `static UIDrawCall Create (string name, UIPanel pan, Material mat, Texture tex, Shader shader) ``{  ``    UIDrawCall dc = Create(name); ``    dc.gameObject.layer = pan.cachedGameObject.layer; ``    dc.baseMaterial = mat; ``    dc.mainTexture = tex; ``    dc.shader = shader; ``    dc.renderQueue = pan.startingRenderQueue; ``    dc.sortingOrder = pan.sortingOrder; ``    dc.manager = pan; ``#if UNITY_EDITOR && UNITY_2018_3_OR_NEWER ``    // We need to perform this check here and not in Create (string) to get to manager reference ``    var prefabStage = UnityEditor.Experimental.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage (); ``    if (prefabStage != null && dc.manager != null) ``    {  ``        // If prefab stage exists and new daw call ``        var stage = UnityEditor.SceneManagement.StageUtility.GetStageHandle (dc.manager.gameObject); ``        if (stage == prefabStage.stageHandle) ``            UnityEngine.SceneManagement.SceneManager.MoveGameObjectToScene (dc.gameObject, prefabStage.scene); ``} ``#endif ``    return dc; ``} `

标签: #unity怎么把场景转为prefab #unity场景导出obj