社区交流|每周Unity Q&A
Unity技术支持工程师陈嘉栋每周都会总结出,过去一周在Unity官方社区交流群中比较有代表性的问题。本篇文章涵盖了IL2CPP、脚本、VR、图形、编辑器、地形等多个方面,着重介绍在原生的地形系统中使用ASTC格式纹理导致Crash的问题。
社区交流Q&A回顾:
地形
问题01:在Unity 2018.1版本中,地形使用的纹理格式为ASTC,手机上出现了崩溃的问题,如何解决?
回答:这是一个Bug,已在Unity 2018.3 beta以及Unity 2018.2.4 f1版本中进行修复。目前在原生地形中使用ETC2格式的纹理是没有问题的。所以建议在地形中使用ETC2纹理格式。
我们可以通过Crash日志信息,来看看程序是在哪一步Crash掉的。下面分享如何通过Crash日志来还原堆栈信息。
以使用Unity 2018.1.0f1,以及使用的Script Backend是Mono为例。打开手机上的测试程序,查看程序Crash时的日志,如下图所示。
在这份堆栈信息里,我们可以看到例如0049b647这样的数字,它们是在Crash时,程序正在执行的方法的内存地址。每行的结尾则是所使用的库,这里是libunity.so。但内存地址对我们而言没有什么意义,所以下面我们需要将内存地址转换成可以看懂的内容。
在Unity 5.3.6之后的版本都提供了libunity的符号表。
在Mac上,符号表的路径是:
/Applications/Unity/PlaybackEngines/AndroidPlayer/Variations/mono/Release/Symbols
在Windows上,符号表的路径是:
C:\Program Files\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Symbols\armeabi-v7a\libunity.sym.so
有了符号表,接下来我们还需要NDK的addr2line工具。你可以在NDK目录下找到:
toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-addr2line
万事俱备,接下来我们解析第一条内存地址所对应的方法。
./arm-linux-androideabi-addr2line -f -C -e libunity.sym.so 0049b647
可以看到Crash的方法是:
construct_block_size_descriptor_2d似乎还不太明显。我们再往回追。
原来是在做DecompressASTC相关的操作时Crash了。
请注意:使用的符号表版本一定要和打包所使用的Unity编辑器版本一致。
Plugins
问题02:Unity是否在Android平台支持64位动态库的调用?
回答:在Unity2018.1.0 Beta 2版本中提供了对 Android 64-bit ARM(experimental)的支持。而在Unity 2018.2正式版中,对ARM64的支持应该已经很完善了。
请将Scripting backend设置为IL2CPP后,就可以在Player Setting中选择ARM 64了。
编辑器
问题03:如何获取Animationclip的检视窗口显示的该资源的内存占用大小数据?
回答:可以调用AnimationUtility.GetAnimationClipStats(clip)来获取某个Clip的状态,即AnimationClipStats类的实例,其中的Size字段即检视窗口显示的内存占用大小。
请参考下面的代码:
Assembly asm = Assembly.GetAssembly(typeof(Editor));
getAnimationClipStats = typeof(AnimationUtility).GetMethod("GetAnimationClipStats", BindingFlags.Static | BindingFlags.NonPublic);
Type aniclipstats = asm.GetType("UnityEditor.AnimationClipStats");
sizeInfo = aniclipstats.GetField("size", BindingFlags.Public | BindingFlags.Instance);
另外,C#部分有开源的代码。请参考Github上的代码:
https://github.com/Unity-Technologies/UnityCsReference/blob/3cfc6c4729d5cacedf67a38df5de1bfffb5994a3/Editor/Mono/Inspector/AnimationClipEditor.cs
图形
问题04:Tonemapping和打包设置里Colorspace是冲突的吗?使用Ronemapping,Colorspace是否需要设置为线性?
回答: 使用Tonemapping要用到HDR,最好和线性空间一起用,才能保证准确度。如果项目设置为Gamma的话,Postprocessing中的Color Grading会有一个警告的。
问题05: 摄像机可以开HDR,但是打包到手机渲染设置中默认是不开的,是否可以使用HDR计算出来的结果,通过Mapping转换成LDR给手机显示?
回答: Tonemapping的作用也是为了将一个高动态范围的颜色数据映射回可用颜色空间,为的是不被显示屏幕截断色彩。因为显示器很少支持HDR,Android手机更是565颜色居多。Tonemap就是一个简单S曲线Remapping。
问题06:摄像机开启HDR并不表示移动端开启HDR吗?
回答:手机上不是固定fp16的,可以自行调整,如果设置没有Hdr backbuffer, 则摄像机上的标记也没有用。
下面是一些相关的小贴士,帮助大家科普Graphic Setting中的各个tier和设备的对应关系。Graphics Settings内的Tier设置,在运行时会根据GPU来选择对应的Tier。应用相关的设置。具体各个Tier和设备的对应关系如下:
Tier 1:
Android - all devices that have support for OpenGL ES 2 only
iOS - all devices before iPhone 5S (not including 5S, but including 5C), iPods up to and including 5th generation, iPads up to 4th generation, iPad mini first generation
Desktops: DirectX 9, HoloLens
Tier 2:
Android - all devices with OpenGL ES 3 support,Vulkan
iOS - all devices starting from iPhone 5S, iPad Air, iPad mini 2nd generation, iPod 6th generation
AppleTV
Tier 3:
Desktops: OpenGL, Metal, DirectX 11+,Vulkan
具体内容请查阅相关文档。
问题07:如何实现雪地踩踏的效果,需要曲面细分的效果,类似《古墓丽影》这样的效果?
回答:思路并不复杂,就是Mesh变形。
《古墓丽影》的实现,请参考:
http://tombraider.tumblr.com/post/131825841425/dev-blog-snow-tech-and-houdini-simulations-mike
你也可以参考文章《利用Shader给斯坦福兔子长毛和实现雪地效果》:
https://www.cnblogs.com/murongxiaopifu/p/7887614.html
问题08:如何实现一团纹理在球上面随机方向位移,并且随时间变化?
回答:采样的时候以_Time作为种子取个噪声即可,请参考《Shader特效—实现“噪声”》:
https://blog.csdn.net/panda1234lee/article/details/52085375
问题09: 如何实现扰动的方向是随机的?在脚本里Setfloat感觉是硬切的。
回答:可以从一张噪声贴图里读取。
请参考与失真效果的文章《着色器-冰效果》:
https://zhuanlan.zhihu.com/p/37696836
问题10:Unity自带的屏幕射线反射效果一般,有更好的推荐吗?
回答:可以参考文章《Unity_StochasticScreenSpaceReflection-实现篇》:
https://zhuanlan.zhihu.com/p/38303394
IL2CPP
问题11:GZipStream在Unity编辑器中工作正常,但Android手机上没办法正常工作。查看Logcat发现在执行时抛出了下面的异常,如何解决?
回答: 如果项目的Scripting backend使用的是Mono,则在使用System.IO.Compression命名空间时的确会抛出类似上面的异常。但是如果使用IL2CPP的话,System.IO.Compression命名空间是可以正常使用的,包括GZipStream同样也是可以正常使用的。
脚本
问题12:如何求一个数最大能是2的多少次幂啊? 例如:513最大是2的9次幂,就多了一位数。Math里有没有这样的方法,我想要模拟Cullingmask那样的筛选层。
回答:范围小用查表,尽量限制在512之内。范围大用位移 ,但不要用浮点运算。
请参考下面的代码:
int Exp(int i)
{
int counter = 0;
while(i > 1)
{
i = i >> 1;
counter++;
}
return counter;
}
void outpuLayers(int layerValue)
{
while(layerValue > 0)
{
int i = layerValue;
int counter = 0;
while (i > 0)
{
i = i >> 1;
counter++;
}
Debug.Log(counter);
i = 1;
while (counter > 1)
{
counter--;
i = i << 1;
}
layerValue = layerValue ^ I;
}
}
VR
问题13:在Unity 2017.1中进行开发Windows Mixed Reality时,Unity编辑器会报错“RenderTexture.GenerateMips failed: render texture does not have mip maps (set useMipMap to true).”这是一个Bug吗?
回答:这是一个Bug,已经在Unity 2017.4版本中进行修复。
需要特别说明的是Unity 2017.4是LTS版本,会持续修复已知的所有Bug,所以建议使用Unity 2017.4进行开发。Unity版本说明请参考:Unity全新的版本发布计划。
小结
以上就是过去一周Unity官方社区交流群中比较有代表性的问题,其中有你关注的问题吗?如果你也希望与Unity的技术工程师交流,欢迎加入Unity官方社区交流群:629212643 或访问Unity官方中文论坛(Unitychina.cn)!
推荐阅读
优惠促销
8月Asset Store资源商店促销
8月期间,只需在Asset Store资源商店消费满50-255美元,即可获赠2-6款精品资源,最高消费250美元,更可附赠获得一件Asset Store定制款T恤!
活动地址:
https://assetstore.unity.com/g/august-promo-activation-demo
点击“阅读原文”访问Unity官方中文论坛