本篇讲解的是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('/') + , currentScene.LastIndexOf('.') - currentScene.LastIndexOf('/') - );
string fileName = exportPath + currentSceneName + ".unity3d";
BuildPipeline.BuildStreamedSceneAssetBundle(new string[] { 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('/') + , levelPath.LastIndexOf('.') - levelPath.LastIndexOf('/') - );
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="" rotY="180.6732" rotZ="" scaleX="1.293338" scaleY="1.293338" scaleZ="1.293338" />
<MeshRenderer>
<Mesh Mesh="TestMesh01" Shader="Diffuse">
<Color hasColor="False" />
<Lightmap IsStatic="True" LightmapIndex="" 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="" />
<Lightmap IsStatic="True" LightmapIndex="" OffsetX="0.1435547" OffsetY="0.1435547" OffsetZ="0.3969002" OffsetW="-0.0005607605" />
</Mesh>
</MeshRenderer>
</Node>
......

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

AssetBundle系列——场景资源之打包(一)的更多相关文章

  1. AssetBundle系列——场景资源之解包(二)

    本篇接着上一篇继续和大家分享场景资源这一主题,主要包括两个方面: (1)加载场景 场景异步加载的代码比较简单,如下所示: private IEnumerator LoadLevelCoroutine( ...

  2. AssetBundle系列——共享资源打包/依赖资源打包

    有人在之前的博客中问我有关共享资源打包的代码,其实这一块很简单,就两个函数: BuildPipeline.PushAssetDependencies():依赖资源压栈: BuildPipeline.P ...

  3. (转)AssetBundle系列——共享资源打包/依赖资源打包

    有人在之前的博客中问我有关共享资源打包的代码,其实这一块很简单,就两个函数: BuildPipeline.PushAssetDependencies():依赖资源压栈: BuildPipeline.P ...

  4. AssetBundle系列——游戏资源打包(二)

    本篇接着上一篇.上篇中说到的4步的代码分别如下所示: (1)将资源打包成assetbundle,并放到自定目录下 using UnityEditor; using UnityEngine; using ...

  5. AssetBundle系列——游戏资源打包(一)

    将本地资源打包,然后放到资源服务器上供游戏客户端下载或更新.服务器上包含以下资源列表:(1)游戏内容资源assetbundle(2)资源维护列表,包含每个资源的名字(完整路径名)和对应的版本号[资源名 ...

  6. [Unity Asset]AssetBundle系列——游戏资源打包

    转载:http://www.cnblogs.com/sifenkesi/p/3557231.html 将本地资源打包,然后放到资源服务器上供游戏客户端下载或更新.服务器上包含以下资源列表:(1)游戏内 ...

  7. (转)AssetBundle系列——游戏资源打包(二)

    转自:http://www.cnblogs.com/sifenkesi/p/3557290.html 本篇接着上一篇.上篇中说到的4步的代码分别如下所示: (1)将资源打包成assetbundle,并 ...

  8. (转)AssetBundle系列——游戏资源打包(一)

    转自:http://www.cnblogs.com/sifenkesi/p/3557231.html 将本地资源打包,然后放到资源服务器上供游戏客户端下载或更新.服务器上包含以下资源列表:(1)游戏内 ...

  9. Unity 关于AssetBundle读取场景

    一. 1.关于如何打包成ab包,就不多说了,网上很多教程,siki学院也有siki老师的免费视频教程挺详细的,可以看看 http://www.sikiedu.com/my/course/74 2.为了 ...

随机推荐

  1. Liferay7 BPM门户开发之30: 通用帮助类Validator、ArrayUtil、StringUtil等使用

    废话不多说,直接上代码. 验证类Validator 主要是空验证.数字.格式验证 调用的例子: protected void validateEmailFrom(ActionRequest actio ...

  2. css之属性部分

    这篇写的是今天的学习到的属性,一共20个. 属性再多,但也要会使用,会在使用时可以记起它,才能起到它为我们所需要的作用. 样式属性 1.border CSS边框属性允许你指定一个元素边框的样式和颜色. ...

  3. WORD2003电子签名插件(支持手写、签章)

    1.引言 WORD电子签名插件,支持手写.本地电子图章.以及网络图章功能.软件使用VC6,以ATL方式编写,软件小巧精致. 这是我学习ATL的成果,学习过程及程序的编写,前前后后共用了一个多月的时间, ...

  4. android: SQLite 数据库的最佳实践

    6.5.1    使用事务 前面我们已经知道,SQLite 数据库是支持事务的,事务的特性可以保证让某一系列的操 作要么全部完成,要么一个都不会完成.那么在什么情况下才需要使用事务呢?想象以下场 景, ...

  5. HOWTO - 压缩封装的Setup.exe(纯MSI)安装包获取运行Log

    在InstallShield中我们有时即使选择Basic MSI工程,但有时还是将MSI封装到Setup.exe中交付. 那么出现运行异常如何获取Log,可以用下面的方法: Setup.exe /v& ...

  6. Revit如何修改三维视图背景色

    Revit中默认的三维视图背景色为白色,有时候为了让现实效果更佳逼真,需要将三维视图背景色设置为天空色,只需在三维视图属性中打开"图形显示选项"即可对三维视图背景色进行设置.

  7. 兼容iOS 10 资料整理

    1.Notification(通知) 自从Notification被引入之后,苹果就不断的更新优化,但这些更新优化只是小打小闹,直至现在iOS 10开始真正的进行大改重构,这让开发者也体会到UserN ...

  8. HiveServer2 的jdbc方式创建udf的修改(add jar 最好不要使用),否则会造成异常: java.sql.SQLException: Error while processing statement: null

    自从Hive0.13.0开始,使用HiveServer2 的jdbc方式创建udf的临时函数的方法由: ADD JAR ${HiveUDFJarPath} create TEMPORARY funct ...

  9. Hibernate不调用update却自动更新

    案例: TInfCustomer cus = (TInfCustomer) this.baseDao.getOne(helper); cus.setXXX cus .setXXX 不调用update也 ...

  10. Android定位&地图&导航——自定义公交路线代码

    一.问题描述 基于百度地图实现检索指定城市指定公交的交通路线图,效果如图所示 二.通用组件Application类,主要创建并初始化BMapManager public class App exten ...