最近比较忙,好久没有更新博客了,新项目切换到unity5.x后使用了新的打包机制,在打包shader的时候遇到了一些问题,这里来记录一下吧。

在上一个项目中,我们使用unity4.7,对于shader并没有进行依赖打包,而是由unity打包到了每个用到的AssetBundle中去,其实这样是“很不科学的”。这样不仅增加了ab的总体积,而且还会在运行时产生很多的shader实例,增加很多的显存占用。所以我们决定把自定义的shader打包成一个AssetBundle。

用到的工具:

1、UnityStudio:https://github.com/Perfare/UnityStudio/releases

这是一个解包AssetBundle的工具,可以查看和导出ab中的资源。

2、Unity自带的profiler

下面是一些尝试和结果分析:

一、不进行依赖打包(不需要设置GraphicsSetting,不给自定义shader设置AssetBundle Name)

这种情况unity5.x还是与unity4.x一样,把shader打包到每一个使用它的AssetBundle 中去,这样就会同时存在多个一样的shader,并在运行时产生多个shader实例。

如下图:

这个Character是我们自定义的一个shader,在运行时产生了多个实例:

使用UnityStudio解包一个ab可以看到,我们自定义的shader ParticlesAlphaTintColor被打包到ab中:

打包后的运行测试结果如下:

1、编辑器是pc平台的时候,打出来的包在编辑器里运行是正常的。

2、编辑器是安卓时,打出来的包在编辑器里运行显示粉红(查看材质可以发现并不是丢失材质和shader),但在手机正常。

这是为什么呢?这是因为以安卓为平台打包的时候被打包的shader被编译成安卓平台的版本,在unity编辑器中运行会发生异常。这是从4.x到5.x一直有的问题。

解包后我们可以看到不同平台编译出来的shader subProgram不同。

Pc:

安卓:

二、依赖打包(将shader设置AssetBundle Name打包)

使用这种方式,需要将shader添加到GraphicsSetting-> always included shader设置中,否则shader也会显示粉红。注意要在设置Graphics之后把shader重新打包,在能生效。

文档中也有说到:https://docs.unity3d.com/Manual/class-GraphicsSettings.html

测试结果如下:

1、编辑器是pc平台的时候,打出来的包在编辑器里运行是正常的。

2、编辑器是安卓时,打出来的包在编辑器里运行显示粉红(查看材质可以发现并不是丢失材质和shader),但在手机正常,原因同上。

再使用profiler查看,可以发现shader可以被物体共用了,随着物体数量的增加也不会产生多个shader实例。(下图有两个Character是因为编辑器中ShaderVariantCollection跟踪到了这个shader,也算一个引用)

这时解包模型的ab,也不会看到shader被打进ab中了,它们只存在与自己的ab包中。

三、注意事项

1、细心的朋友会发现,一中我们profiler中看到的Character是45.7k,而二中是334k,这是因为Character是一个多变体的shader,而加入了GraphicsSetting-> always included shader后,会将它所有的变体打包到游戏中。

2、在测试打包的过程中我发现一个有趣的现象--- unity5.4和4.x打包后的shader解包(非依赖打包)出来看起来不一样:

5.4没有看到代码,而是看到GPUProgramID

而4.7是直接看到代码

结合最新更新的unity5.5的更新日志,似乎可以看出点端倪:

https://unity3d.com/cn/unity/whats-new/unity-5.5.0

---Shaders: Shaders are now exported to the Unity player completely in binary. There is no Shader text string and parsing in run time.

3、关于untiy内置shader

如果没有设置到GraphicsSetting-> always included shader中,那么会打包到依赖它的ab中,如果设置了就不会打包进去。而是再构建的时候,就导入到你的游戏。

4、手动设置shader 加入GraphicsSetting-> always included shader很麻烦,怎么办?

其实是可以使用代码设置的:

来自:http://www.hiwrz.com/2016/04/18/unity/175/

  1. [MenuItem("Test/测试设置included shader", false, 11)]
  2. public static void TestIncludedShader()
  3. {
  4. string[] myShaders = new string[1]{
  5. "Legacy Shaders/Diffuse"
  6. };
  7. SerializedObject graphicsSettings = new SerializedObject (AssetDatabase.LoadAllAssetsAtPath ("ProjectSettings/GraphicsSettings.asset") [0]);
  8. SerializedProperty it = graphicsSettings.GetIterator ();
  9. SerializedProperty dataPoint;
  10. while (it.NextVisible(true)) {
  11. if (it.name == "m_AlwaysIncludedShaders") {
  12. it.ClearArray();
  13. for (int i = 0; i < myShaders.Length; i++) {
  14. it.InsertArrayElementAtIndex(i);
  15. dataPoint = it.GetArrayElementAtIndex (i);
  16. dataPoint.objectReferenceValue = Shader.Find(myShaders[i]);
  17. }
  18. graphicsSettings.ApplyModifiedProperties ();
  19. }
  20. }
  21. }

5、加入AlwaysIncludedShaders的shader是开始游戏的时候就全部编译了吗?

答案是不会,加到always include 的shader,会将shader的所有变体打包到游戏,用到的时候才会加载用到的变体到内存!需要预加载变体可以使用:ShaderVariantCollection

相关文档:https://docs.unity3d.com/Manual/OptimizingShaderLoadTime.html

值得注意的是unity5.x内置的  Standard shader是一个有成千上万变体的shader,要谨慎的把它加入到GraphicsSetting-> always included shader,因为1中的原因,会使得你的包体非常大,打包也非常耗时。至少在我测试下是一直卡在这个界面到下班都没有响应。。

文档里面也有提到:

6、关于shader加载和预热的一些资料:

Unity - Manual: Optimizing Shader Load Time

https://docs.unity3d.com/ScriptReference/ShaderVariantCollection.html

http://www.seven-fire.cn/archives/174

https://www.zhihu.com/question/30087487

https://zhuanlan.zhihu.com/p/21949663

Unity5.x shader打包AssetBundle总结的更多相关文章

  1. 实力封装:Unity打包AssetBundle(一)

    说明:这是一系列循序渐进的教程,今天先介绍最简单的AssetBundle打包方式. 这是一个由在Unity中需要加载模型而引发出来的一系列坑,为了填坑花了不少时间,如果有需要在Unity中自定义菜单, ...

  2. Unity 5.X扩展编辑器之打包assetbundle

    5.x的assetbundle与4.x以及之前的版本有些不同,不过本质是一样的,只不过5.x打包assetbundle更为简单和人性化了,总体来说只需要三个步骤: 第一步:创建打包资源 //这里是一个 ...

  3. 实力封装:Unity打包AssetBundle(大结局)

    →→前情提要:让用户选择要打包的文件←← 大结局:更多选择 Unity打包AssetBundle从入门到放弃系列终于要迎来大结局了[小哥哥表示实在写不动了o(╥﹏╥)o]... 经过上一次的教程,其实 ...

  4. Unity3D的坑系列:打包Assetbundle丢失Shader问题(贴图显示不了)

    从Unity4.2开始,为了减少首包大小,不会默认将所有Shader引擎加到游戏程序中,据Unity技术支持人员所说,Unity会将Shader引擎打包到Assetbundle资源中,但是我测试发现不 ...

  5. Unity最新版打包AssetBundle和加载的方法

    一.设置assetBundleName二.构建AssetBundle包三.上传AssetBundle到服务器四.把AssetBundle放到本地五.操作AssetBundle六.完整例子七.Asset ...

  6. Unity中Shader和AssetBundle结合使用的注意事项

    之前遇到了一件事情就是打包安卓的ab后,unity在editor启动下,加载出来的abshader丢失,其实发布安卓后运行是正常的,当时还纠结了半天,还写了个重新赋值的脚本 下面是unity开发的一些 ...

  7. Unity手游之路<十一>资源打包Assetbundle

    http://blog.csdn.net/janeky/article/details/17652021 在手游的运营过程中,更新资源是比不可少的.资源管理第一步是资源打包.传统的打包可以将所有物件制 ...

  8. 实力封装:Unity打包AssetBundle(番外篇)

    前情提要:第二种打包方式. 自定义AssetBundle包扩展名 在之前的教程中,我们已经多次提到过扩展名了,并且也已经说明了如何设置自定义的AssetBundle扩展名.至于为什么还要把它单独拿出来 ...

  9. 实力封装:Unity打包AssetBundle(三)

    前情提要:第二种打包方式 窗口初现 通过前面的两篇教程和一篇番外,我们已经完全实现了打包的功能.但是使用起来总是觉得有些晦涩别扭,如果不告诉别人怎么使用,对方肯定是一头雾水. What?你给我的这是啥 ...

随机推荐

  1. activiti helloworld 续

    todo... 8.开发流程部署功能 9.开发简单任务待办功能 10.开发简单任务办理功能 11.开发页面activiti流程跟踪图形展现功能 12.集成网页流程设计器

  2. /dev/null和/dev/zero的区别

    /dev/null,外号叫无底洞,你可以向它输出任何数据,它通吃,并且不会撑着!/dev/zero,是一个输入设备,你可你用它来初始化文件. /dev/null------它是空设备,也称为位桶(bi ...

  3. 3.命名规范《.NET设计规范》

    3.命名规范 3.1 大小写约定 使用合适的大小写增强名字可读性. 3.1.1 标识符的大小写规则 标识符的每个单词首写字幕大写.不要用下划线. PascalCasing camelCasing Pa ...

  4. HTML5练习4

    1.菜单条 主要代码 <!doctype html> <html> <head> <meta charset="utf-8"> &l ...

  5. 【AtCoder】Dwango Programming Contest V题解

    A - Thumbnail 题意简述:给出N个数,找出N个数中和这N个数平均值绝对值最小的数 根据题意写代码即可= = #include <bits/stdc++.h> #define f ...

  6. linux下常用的日志分析命令

    linux下常用的日志分析命令   本文介绍下,在linux中常用的一些分析日志的命令行或脚本,有需要的朋友参考下.     形如下面这样的access.log日志内容: 211.123.23.133 ...

  7. Codeforces 311B Cats Transport 斜率优化dp

    Cats Transport 出发时间居然能是负的,我服了... 卡了我十几次, 我一直以为斜率优化写搓了. 我们能得出dp方程式 dp[ i ][ j ] = min(dp[ k ][ j - 1 ...

  8. 【Java】 大话数据结构(1) 线性表之顺序存储结构

     本文根据<大话数据结构>一书,实现了Java版的顺序存储结构. 顺序存储结构指的是用一段地址连续的存储单元一次存储线性表的数据元素,一般用一维数组来实现. 书中的线性表抽象数据类型定义如 ...

  9. ADNI数据集相关概念整理

    数据类型 临床 遗传 MRI图像 PET图像 生物样本 临床 ADNI临床数据集包括关于每个受试者的临床信息,包括招募,人口统计学,身体检查和认知评估数据.可以将整套临床数据作为逗号分隔值(CSV)文 ...

  10. [转]关于一些SPFA的标程

    SPFA算法 求单源最短路的SPFA算法的全称是:Shortest Path Faster Algorithm. 最短路径快速算法-SPFA算法是西南交通大学段凡丁于1994年发表的. 适用范围:给定 ...