AssetBundle系列——場景資源之打包(一)

本篇講解的是3D遊戲的場景資源打包方式,首先簡單的分析一下場景中所包含的資源的類型。函數

場景資源通常包含:地表模型(或者是Unity Terrain),非實例化物體(攝像機、空氣牆、光源、各類邏輯物體之類的)、場景物體(花草樹木、房子箱子之類的)。ui

由於場景物體大可能是公用的,因此將場景物體都打成單獨的包,將地表模型、非實例化物體打包到場景包中spa

那麼場景TestScene所對應的資源就包括:場景包TestScene.unity3d、場景資源配表TestSceneXML.xml。3d

打包場景單個物體的具體細節在前面的帖子中已有講解,此處再也不贅述,本帖主要分享場景自己的打包和場景資源的序列化。code

(1)打包一個場景orm

打包當前場景的代碼以下所示,使用BuildStreamedSceneAssetBundle和BuildPlayer函數均可以實現此功能。xml

public class PackScene
{
    public static void Execute(UnityEditor.BuildTarget target)
    {
        string assetPath = SceneAssetProcesser.GetPlatformPath(target);

        string exportPath = assetPath + "Scene/";
        if (Directory.Exists(exportPath) == false)
            Directory.CreateDirectory(exportPath);

        string currentScene = EditorApplication.currentScene;
        string currentSceneName = currentScene.Substring(currentScene.LastIndexOf('/') + 1, currentScene.LastIndexOf('.') - currentScene.LastIndexOf('/') - 1);
        string fileName = exportPath + currentSceneName + ".unity3d";
        BuildPipeline.BuildStreamedSceneAssetBundle(new string[1] { EditorApplication.currentScene }, fileName, target);
        // 另一種方式
        // BuildPipeline.BuildPlayer(new string[1] { EditorApplication.currentScene }, fileName, target, BuildOptions.BuildAdditionalStreamedScenes);
    }

}

將TestScene打包成TestScene.unity3d的包。htm

(2)序列化場景物體對象

對於一個場景物體,主要序列化其下列信息:blog

(1)Transform信息:位置、朝向、縮放

(2)Mesh信息:Shader名字

        主顏色Color

        光照貼圖信息:是否爲static對象(static的對象纔有光照貼圖屬性)、LightmapIndex、LightmapTilingOffset

主體代碼以下所示:

  public static void ExportXML(string savePath)
    {
        // 全部的動態加載的物體都掛在ActiveObjectRoot下面
        GameObject parent = GameObject.Find("ActiveObjectRoot");
        if (parent == null)
        {
            Debug.LogError("No ActiveObjectRoot Node!");
            return;
        }

        XmlDocument XmlDoc = new XmlDocument();
        XmlElement XmlRoot = XmlDoc.CreateElement("Root");
        XmlRoot.SetAttribute("level", EditorApplication.currentScene);
        XmlDoc.AppendChild(XmlRoot);

        foreach (Transform tranGroup in parent.transform)
        {
            XmlElement xmlGroupNode = XmlDoc.CreateElement("Group");
            XmlRoot.AppendChild(xmlGroupNode);

            CreateTransformNode(XmlDoc, xmlGroupNode, tranGroup);

            foreach (Transform tranNode in tranGroup.transform)
            {
                XmlElement xmlNode = XmlDoc.CreateElement("Node");
                xmlGroupNode.AppendChild(xmlNode);

                CreateTransformNode(XmlDoc, xmlNode, tranNode);
                CreateMeshNode(XmlDoc, xmlNode, tranNode);
            }
        }

        string path = savePath + "Scene/";
        if (Directory.Exists(path) == false)
            Directory.CreateDirectory(path);
        string levelPath = EditorApplication.currentScene;
        string levelName = levelPath.Substring(levelPath.LastIndexOf('/') + 1, levelPath.LastIndexOf('.') - levelPath.LastIndexOf('/') - 1);
        XmlDoc.Save(path + "Xml" + levelName + ".xml");
        XmlDoc = null;
    }

    private static void CreateTransformNode(XmlDocument XmlDoc, XmlElement xmlNode, Transform tran)
    {
        if (XmlDoc == null || xmlNode == null || tran == null)
            return;

        XmlElement xmlProp = XmlDoc.CreateElement("Transform");
        xmlNode.AppendChild(xmlProp);

        xmlNode.SetAttribute("name", tran.name);
        xmlProp.SetAttribute("posX", tran.position.x.ToString());
        xmlProp.SetAttribute("posY", tran.position.y.ToString());
        xmlProp.SetAttribute("posZ", tran.position.z.ToString());
        xmlProp.SetAttribute("rotX", tran.eulerAngles.x.ToString());
        xmlProp.SetAttribute("rotY", tran.eulerAngles.y.ToString());
        xmlProp.SetAttribute("rotZ", tran.eulerAngles.z.ToString());
        xmlProp.SetAttribute("scaleX", tran.localScale.x.ToString());
        xmlProp.SetAttribute("scaleY", tran.localScale.y.ToString());
        xmlProp.SetAttribute("scaleZ", tran.localScale.z.ToString());
    }

    private static void CreateMeshNode(XmlDocument XmlDoc, XmlElement xmlNode, Transform tran)
    {
        if (XmlDoc == null || xmlNode == null || tran == null)
            return;

        XmlElement xmlProp = XmlDoc.CreateElement("MeshRenderer");
        xmlNode.AppendChild(xmlProp);

        foreach (MeshRenderer mr in tran.gameObject.GetComponentsInChildren<MeshRenderer>(true))
        {
            if (mr.material != null)
            {
                XmlElement xmlMesh = XmlDoc.CreateElement("Mesh");
                xmlProp.AppendChild(xmlMesh);

                // 記錄Mesh名字和Shader
                xmlMesh.SetAttribute("Mesh", mr.name);
                xmlMesh.SetAttribute("Shader", mr.material.shader.name);

                // 記錄主顏色
                XmlElement xmlColor = XmlDoc.CreateElement("Color");
                xmlMesh.AppendChild(xmlColor);
                bool hasColor = mr.material.HasProperty("_Color");
                xmlColor.SetAttribute("hasColor", hasColor.ToString());
                if (hasColor)
                {
                    xmlColor.SetAttribute("r", mr.material.color.r.ToString());
                    xmlColor.SetAttribute("g", mr.material.color.g.ToString());
                    xmlColor.SetAttribute("b", mr.material.color.b.ToString());
                    xmlColor.SetAttribute("a", mr.material.color.a.ToString());
                }

                // 光照貼圖信息
                XmlElement xmlLightmap = XmlDoc.CreateElement("Lightmap");
                xmlMesh.AppendChild(xmlLightmap);
                // 是否爲static,static的對象纔有lightmap信息
                xmlLightmap.SetAttribute("IsStatic", mr.gameObject.isStatic.ToString());
                xmlLightmap.SetAttribute("LightmapIndex", mr.lightmapIndex.ToString());
                xmlLightmap.SetAttribute("OffsetX", mr.lightmapTilingOffset.x.ToString());
                xmlLightmap.SetAttribute("OffsetY", mr.lightmapTilingOffset.y.ToString());
                xmlLightmap.SetAttribute("OffsetZ", mr.lightmapTilingOffset.z.ToString());
                xmlLightmap.SetAttribute("OffsetW", mr.lightmapTilingOffset.w.ToString());
            }
        }
    }

生成的配表結構以下:

......
<Node name="TestObject"> <Transform posX="-25.13055" posY="12.99786" posZ="26.41202" rotX="0" rotY="180.6732" rotZ="0" scaleX="1.293338" scaleY="1.293338" scaleZ="1.293338" /> <MeshRenderer> <Mesh Mesh="TestMesh01" Shader="Diffuse"> <Color hasColor="False" /> <Lightmap IsStatic="True" LightmapIndex="3" OffsetX="0.06542969" OffsetY="0.06542969" OffsetZ="0.09154129" OffsetW="0.4391975" /> </Mesh> <Mesh Mesh="TestMesh02" Shader="AlphaTest"> <Color hasColor="True" r="0.5429823" g="0.8897059" b="0.6888453" a="1" /> <Lightmap IsStatic="True" LightmapIndex="2" OffsetX="0.1435547" OffsetY="0.1435547" OffsetZ="0.3969002" OffsetW="-0.0005607605" /> </Mesh> </MeshRenderer> </Node>
......

 下一篇講解根據上述配表生成場景的具體實現...

相關文章
相關標籤/搜索