本篇讲解的是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()); } } } 生成的配表结构如下: ...... 下一篇讲解根据上述配表生成场景的具体实现... |
|