AssetBundle里的Shader问题

   2017-02-05 0
核心提示:关于Resources和AssetBundle优劣之前已经提过很多次了(参考官方教程The Resources folder),正好最近@张迪在做框架AssetBundle部分的优化,特此整理一下两个特常见的坑及对应解决办法。之前在关于Unity中的资源管理,你可能遇到这些问题里有有人提到过这个问

关于Resources和AssetBundle优劣之前已经提过很多次了(参考官方教程 The Resources folder ),正好最近@张迪在做框架AssetBundle部分的优化,特此整理一下两个特常见的坑及对应解决办法。之前在 关于Unity中的资源管理,你可能遇到这些问题 里有有人提到过这个问题:

Q6: 请问粒子特效的Shader是否不能使用依赖打包? 我们对Shader的模型和特效使用了依赖打包,运行的时候发现模型显示是正常的,但是粒子特效使用的Shader就不能正常运行,特效显示不正常。而在编辑器中,我们看到Material中的Shader是存在的。这时候如果重新手动给这个Material指定同样的Shader,这个粒子特效就能正常显示,请问这是什么原因引起的?

这里主要分享如何在编辑器里模拟AssetBundle时处理Shader(之后我们会分享『如何从框架层面实现0冗余』相关经验)

在我们的框架里是这么区分资源的:

  • Editor模式
    • 开发时直接使用 UnityEditor.AssetDatabase.LoadAssetAtPath 加载
    • 也支持模拟真机行为,使用打包出来的AssetBundle文件
  • Player模式:真机使用StreamingAssets下自带的或热更新下载的AssetBundle文件

在开发过程中,Editor模拟模式下会有一个非常麻烦的情况:Android或iOS模式下加载出来的材质球都是紫色的。官方支持里有提到这个问题 Shaders Are Pink When Loaded From An AssetBundle ,论坛里也有相关讨论 Shaders and asset bundles 。根据我的理解,问题就出在:打包到AssetBundle里的Shader是移动平台版本的,但是编辑器需要的是Windows/OSX版本的。

找到原因之后,我们使用了以下解决方案:

  • 在打包AssetBundle之后,针对所有shader重新打包一个对应编辑器版本的AssetBundle
  • 载入AssetBundle时,如果是shader则载入Windows或OSX版本,同时其他资源载入对应Android或iOS版本
  • 载入GameObject时,编辑器里会有额外处理:找到所有材质球,并在shader AssetBundle里找到同名shader进行替换(因为原材质球是对应的移动版本的shader)

在第一步中,除了需要打包项目内本身所有Shader之外,还需要打包builtin shaders,便于后面几步查找; 第三步利用了反射来修改所有材质球

System.Type materialType = typeof(Material);
Component[] comps = go.GetComponentsInChildren<Component>();
foreach (Component comp in comps)
{
    System.Type t = comp.GetType();

    var fields = t.GetFields();
    foreach (var field in fields)
    {
        if (field.FieldType == materialsType)
        {
            Material mat = field.GetValue(comp) as Material;
            if (mat != null)
            {
                mat = FixMaterial(mat);
                if (mat != null)
                    field.SetValue(comp, mat);
            }
        }
    }
}

这样的最大好处在于 不需要额外的操作 :还有一个解决方案是每个项目里解压一份builtin shader,然后强制使用项目内的版本而不是Resources/unity_builtin_extra下的版本。相比之下我们的解决方案只是在打包编辑器版本shader时解压出来然后及时删除,同时这样替换的比较干净(包括脚本里的 public Material lineMaterial; 这种也能被处理到),不需要任何人工操作。当然代价就是打包的时候比较慢,同时载入的时候使用了反射来查找所有需要替换shader的材质球也有一定的性能损失。

 
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • 移动周刊第 176 期:Android 知识梳理
    移动周刊第 176 期:Android 知识梳理
    写在前面 本期移动周刊第 176 期如约而至,聚焦 Android、iOS、VR/AR/MR、直播等前沿移动开发技术,收录一周最热点,解读开发技巧,每周三移动周刊抢先看,我们希望从中能够让你有一些收获,如果你有好的文章以及优化建议,请发送邮件至mobilehub@csdn.net,
  • Android WebView组件
    Android WebView组件
    原生应用的用户体验不错,但是开发成本相对较高。原生应用的灵活性相对页不如 Web 页,切 Web 页相对原生有更强的控制力。原生应用出了 Bug,如果没有热补丁等热修复技术,应用就需要重新发版上线。Web 页面的控制权都在服务器端,故出了问题,在服务器端修复
  • 热修复框架HotFix源码解析
    热修复框架HotFix源码解析
    讲起 Android 的热修复,相信大家对其都略知一二。热修复可以说是继插件化之后,又一项新的技术。目前的 Android 热修复框架主要分为了两类:基于 Native Hook:使用 JNI 动态改变方法指针,比如有 Dexposed 、 AndFix 等; 基于 Java Dex 分包:改变 dex 加
  • Android 热修复 (Hot Fix) 案例全剖析(一)
    Android 热修复 (Hot Fix) 案例全剖析(一)
    说到热修复技术,我们不得不先谈一下什么是冷修复。冷修复当我们发现上线的应用APK存在Bug,我们通过发布新的应用APK,去替换旧的应用APK,以达到解决Bug的目的,但是这样做存在很大的缺点,需要用户二次下载APK,浪费用户流量,费时、费力、用户体验差。热修
  • Android插件化笔记-2-ClassLoader
    https://zhuanlan.zhihu.com/p/20524252有几个ClassLoader如MainActivity的代码所示,protectedvoidonCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ClassLoader classLoader = getClass
点击排行