首页 >Unity3D频道 >【Unity3D研究院之游戏开发】 > Unity3D脚本复制场景的锅
2022
03-11

Unity3D脚本复制场景的锅

美术制作场景的时候习惯放置一些参照物,由于每次他们都会忘记删除,所以我们制作了一个脚本根据源场景自动生成一份新场景,以节点命名,生成的时候自动删除这些参照物。如下图所示,场景烘焙过,只保留Scene节点,导出新场景其他节点都删除掉。

Unity3D脚本复制场景的锅 - 雨松MOMO程序研究院 - 1
如下图所示,拷贝场景后只保留了Scene节点,其他都删除了。

Unity3D脚本复制场景的锅 - 雨松MOMO程序研究院 - 2
然后看下引用,新生成场景明明是空的为啥会引用已经删除掉的资源呢?这样在打Assetbundle的时候就会打入额外不需要的资源了。

Unity3D脚本复制场景的锅 - 雨松MOMO程序研究院 - 3

原因就是LightingData的锅,需要将新场景拖入LightData才行。

Unity3D脚本复制场景的锅 - 雨松MOMO程序研究院 - 4

每次手动当然不行,一定要自动。用文本打开以下LightingData,发现里面都是二进制,如何改呢?我是一点点试验的,发现可以用SerializedObject来改,如下代码所示,拷贝场景、删除节点、替换LightData里的场景自动完成。

    [MenuItem("1/复制场景")]
    static void CopyScene()
    {

        EditorSceneManager.MarkAllScenesDirty();
        EditorSceneManager.SaveOpenScenes();
        var goArray = EditorSceneManager.GetActiveScene().GetRootGameObjects();
        foreach (var go in goArray)
        {
            if (go.name != "Scene")
            {
                Object.DestroyImmediate(go);
            }
        }

        EditorSceneManager.SaveScene(EditorSceneManager.GetActiveScene(), "Assets/Copy.unity", true);
        var Scene = EditorSceneManager.OpenScene("Assets/Copy.unity");


        LightingDataAsset asset = GameObject.Instantiate(Lightmapping.lightingDataAsset);
        SerializedObject obj = new SerializedObject(asset);
        SerializedProperty property = obj.FindProperty("m_Scene");
        SceneAsset assetscene = AssetDatabase.LoadAssetAtPath<SceneAsset>(Scene.path); //替换新场景
        property.objectReferenceValue = assetscene;
        obj.ApplyModifiedProperties();

        string lightDataPath = AssetDatabase.GetAssetPath(Lightmapping.lightingDataAsset);
        AssetDatabase.CreateAsset(asset, lightDataPath);


        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
    }

这样在打场景Assetbundle才能是最小化的。

最后编辑:
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!

Unity3D脚本复制场景的锅》有 7 条评论

  1. 怀特说:

    有源码的话看下就会发现,确实只序列化了m_Scene这个字段,所以其他的都无法反序列化出来(2021.3版本)

  2. jiahao说:

    对于整体场景使用简单参照物或者2D场景的话,使用ProjectSetting ->Editor ->EdittingEnviroument 更方便,配置一个单独的环境场景,在prefab模式下会叠加一个无法编辑的背景场景

  3. xaolonf说:

    完全看不明白,能讲得通俗易懂点么!!

  4. dotlive说:

    m_Scene以下的字段,FindProperty找不到。。。

  5. jojo59516说:

    我记得Debug模式的Ispector面板上看到的东西就是SerializedObject可视化的结果。所以在那里看到的所有结构都可以通过SerialiedObject获取到。曾经用它来处理过Shader变体统计

    • 雨松MOMO说:

      可以这样说,但是变量名和Inspector面板上的可能不一样。对于这个例子,lightingdata.asset文件里是二进制保存的, 我是使用assetstudio解开发现里面序列化了m_Scene变量,随后尝试替换发现确实解决问题了

留下一个回复

你的email不会被公开。 必填项已用 * 标注。