zoukankan      html  css  js  c++  java
  • AssetBundle系列——场景资源之打包(一)

    本篇讲解的是3D游戏的场景资源打包方式,首先简单的分析一下场景中所包含的资源的类型。

    场景资源一般包含:地表模型(或者是Unity Terrain),非实例化物体(摄像机、空气墙、光源、各种逻辑物体之类的)、场景物体(花草树木、房子箱子之类的)。

    因为场景物体大多是公用的,所以将场景物体都打成单独的包,将地表模型、非实例化物体打包到场景包中

    那么场景TestScene所对应的资源就包括:场景包TestScene.unity3d、场景资源配表TestSceneXML.xml。

    打包场景单个物体的具体细节在前面的帖子中已有讲解,此处不再赘述,本帖主要分享场景本身的打包和场景资源的序列化。

    (1)打包一个场景

    打包当前场景的代码如下所示,使用BuildStreamedSceneAssetBundle和BuildPlayer函数都可以实现此功能。

    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的包。

    (2)序列化场景物体

    对于一个场景物体,主要序列化其下列信息:

    (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>
    ......

     下一篇讲解根据上述配表生成场景的具体实现...

  • 相关阅读:
    Vue.js 转自http://zhuanlan.zhihu.com/evanyou/20302927
    Linux 下的终端
    图像热点(图像地图)
    网页多媒体 flash
    下拉列表
    <input> type 属性
    <form>表单
    表格结构
    简介
    <meta>标记
  • 原文地址:https://www.cnblogs.com/sifenkesi/p/3597106.html
Copyright © 2011-2022 走看看