技术分享连载(二)

技术分享连载(二)

【技术小札】是UWA推出的技术交流栏目,我们会将开发团队中反馈的常见问题加以总结并梳理在此,以供大家参考。同时如果你也是个热爱分享、愿与大家抱团进步的程序员,欢迎加入UWA的QQ群(793972859),与我们奇文分享,疑义相析。


Q1:Lightmap在PC上显示正常,但是转到Android平台上存在色差,颜色普遍偏暗。

一般来讲,有两种情况可能会导致色偏和亮度差异。

1.Unity烘焙的Lightmap是32bit的HDR图,而移动设备通常不支持HDR图(32bit per channel),会按照LDR图(8bit per channel)的形式进行处理,因此会出现色偏问题。因此我们建议:

  • 在移动平台下使用Mobile/Diffuse材质,可载入Standard Assets(Mobile) package获得。如果要获得更合适的效果,需要自行修改Lightmap的DecodeLightmap函数,该函数可在Unity\Editor\Data\CGIncludes\UnityCG.cginc文件中找到。需要说明的是,这种方法也不能达到与PC端完全一致的效果。
  • 如果需要PC和移动平台的显示效果一致,可以用图像编辑软体修改Lightmap為LDR格式,例如PNG(8bit per channel)。
  • 为了避免类似问题,请不要使用过于强烈的Light进行烘焙,因為Light的强度(Intensity)越高,色偏问题会越严重。若有阴影丢失时,可以尝试检查一下模型的Lightmapindex、Lightmapscaleoffset、UV2等影响Lightmap采样的一些参数。

2.另一种可能是存在过曝现象,可以尝试将playersettings -> use direct3d 11关闭,看问题是否解决。


Q2:Lightmap丢失。用Unity5.1.2的AssetBundle做热更新,资源导出的时候分析了所有的依赖项单文件导出。比如在导出场景的时候场景的烘焙出来的LightmapSnapshot.asset文件导出不了,导致运行的时候场景的Lightmap丢失了。

LightmapSnapshot.asset 本身是Editor下使用的,并不能单独被打包进AssetBundle。 运行时加载Lightmap,一种方法是把场景(.unity 文件)打成AssetBundle加载,Lightmap 信息会打入场景AssetBundle(因为Lightmap信息和场景绑定)。另一种是通过Lightmapsettings.Lightmaps方法来运行时设置。需要注意的是,同时还需要重设Prefab的Lightmap信息(Lightmapindex和Lightmapscaleoffset),因为Lightmap信息在Unity 5.x下不会保存在Prefab 上。
另外存在一种可能,Unity 5.x中加入了Shader Stripping功能,在打包时,默认情况下会根据当前场景的Lightmap及Fog设置对资源中的Shader进行代码剥离。这意味着,如果在一个空场景下进行打包,则Bundle中的Shader会失去对Lightmap和Fog的支持,从而出现运行时Lightmap和Fog丢失的情况。 而通过将Edit->Project Settings->Gaphics下Shader Stripping中的modes改为Manual,并勾选相应的Mode即可避免这一问题。


Q3:Unity 5.3版本WWW有泄漏,用Unity的Profiler看不出来内存的变化,但用Android或者iOS的内存查看工具就能发现内存在一直增加。之前同样的步骤测试5.2.3版本就没问题。 如图:

UWA Tech Doc

运行一段时间后

UWA Tech Doc

该问题已经在5.3.3版本中修复。(特此感谢应龙互动张哲童鞋的发现,同时提醒开发者需要关注下自己的开发版本,5.3.3以前类似情况的项目可以参考一下。)


Q4:如果我有一个Prefab,它的Dependencies都在Resources文件夹中,那么,当我在AssetBundle打包时,只打包这个Prefab(不指定BuildAssetBundleOptions.CompleteAssets和BuildAssetBundleOptionsCollectDependencies)的话,这个Prefab能够正确实例化吗?

这是不能正确实例化的,因为AssetBundle中的资源和Resource文件夹下资源是不会建立依赖关系的(脚本除外,因为开启BuildAssetBundleOptionsCollectDependencies 时,脚本依然不会打包到AssetBundle中)。所以会出现Mesh、Material等的丢失。


Q5:假设有两个界面Panel A和Panel B,它们均依赖一个共享Atlas C。AssetBundle打包时,如果我们将其分别打包的话,那么在使用时是否不能将AssetBundle C进行卸载?如果在加载Panel A和B之前,将Atlas C加载到内存中,但是将AssetBundle C进行卸载,那么在加载和实例化Panel A和B时,是否会出问题?

是的,不仅是Panel和Atlas,只要是A或B依赖于C,就必须保证在加载或实例化A或B时,C的AssetBundle一定存在于内存中。如果之前将C对应的AssetBundle进行卸载,则加载或实例化A和B时,引擎将无法自动将C绑定给A和B进行使用。
关于AssetBundle依赖性打包,我们已在之前的分享【揭开AssetBundle庐山真面目】中有所提及。
UWA已支持项目内成员相互邀请,共享测评数据。欢迎开发者邀请其他成员共同加入到项目中来,众志成城,成就优化大业!