内容简介:这是第156篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题,建议阅读时间10分钟,认真读完必有收获。UWA 问答社区:answer.uwa4d.comUWA QQ群2:793972859(原群已满员)
这是第156篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题,建议阅读时间10分钟,认真读完必有收获。
UWA 问答社区:answer.uwa4d.com
UWA QQ群2:793972859(原群已满员)
本期目录:
- 不同种Mesh的DrawCall优化策略
- AnimationClip内存优化
- 渲染效果出错
- Unity编译后报错是否有回调可用
- UGUI图集排列问题
DrawCall
Q:我在制作一款Voxel的游戏,目前游戏内:所有模型均公用同一个Material,每个模型部件(怪)都是单独的Mesh,用Animator制作的动画无骨骼,就是关键帧动画,已开GPU Instance。
遇到的问题:
比如一个角色有10+个部件,当地图上同时出现10种怪时候,模型部分的DrawCall就会飙升到100+。因为目前特效加入不多,所以用真机测试(Mi8 Lite)时候并未出现卡顿效果,并且开了GPU Instance,在种类不多、数量多的情况下运行也良好。
但是还是想问一下各位大神,这个高DrawCall的问题,有什么好的优化方法吗? 或者说有必要优化吗?感谢!
A:自己做Culling+手动调用DrawMeshInstanced(直接材质勾选instance经常合不起来),可以减少到部件种类数个DrawCall。
对动画精度要求不高又肯空间换时间,整个模型按帧动画bake出来,用DrawMeshInstanced可以缩减到模型种类数个DrawCall。
用LWRP/HDRP有个懒人福利,把SRP batcher打开,材质不要(注意是不要)勾选enable instance,如果用的是内置Shader,直接可以看到DrawCall骤减,自定义Shader改写一下也不难。
Animation
Q:有什么好的方法可以优化动画内存占用?除了常见的降低精度、压缩、去Scale等操作外,降低frame Rate是否可行?
A1:关于frame Rate可以补充一下:
如果题主问的是动画导入到Unity后,在播放时改变frame Rate(通过控制动画播放speed,导入Unity后实际已经没法改变动画片段原始frame Rate了),那frame Rate的改变不会影响内存;
但是,如果题主指的是在动画制作软件里(比如3ds Max、Maya)修改frame Rate,那导入到Unity后内存确实会受些影响。此时,如果两个动画一致,单纯frame Rate不同:
1、不开动画压缩时,实际关键帧数多的片段(通常是frame Rate高的),内存会大一些,而且还有几个影响因素:
a、导入时开启resample curves(该选项决定Unity在导入时是否自动插帧,会使所有曲线在播放时间段满帧),那frame Rate高的内存会高很多;
b、不开resample,那frame Rate高的会高一点。
2、开动画压缩时,比如Keyframe Reduction,不同frame Rate的内存再次变得相近(因为动画一致,实际动画曲线也类似,压缩时同样会压缩掉一些重复的数据)。
结论也就是说,当动画压缩选项开启的时候,制作动画时的frame Rate对内存其实影响也不大,所以不需要特意在frame Rate上做优化。
该回答由UWA提供A2:我们可以把一些线性动画进行程序模拟,这样减少动画K帧的数据量,比如常用的iTween、DOTween插件和UWA推荐的XTween等。
渲染
Q:在iPhone上使用Metal API,并且开启MSAA,在渲染不透明物后透明物前这个阶段(例如AfterForwardOpaque)插入任意一个CommandBuffer,会使透明队列中的物体渲染最前面,好像没有了ZTest的样子。
注:使用OpenGL ES3.0没有问题,Android平台上也没有问题。
写了一个重现的Demo,构建到iPhone上运行即可。同时开启MSAA和CommandBuffer会发现两个红色Cube永远在树的前面。关闭其中一项就没问题。
附上重现的Demo:
MASSDemo.zip题主回答:在渲染透明物之后和不透明物之前插入一个CommandBuffer,在这个Cube里把Unity的深度贴图写入到当前FrameBuffer的DepthBuffer里就解决了。
Script
Q:想了解Unity在编译脚本报错时有没什么回调?或者有什么Trick可以用的呢?
A1:试一下效果:
public class CompilePostProcesser : AssetPostprocessor { static CompilePostProcesser() { EditorApplication.update += Update; } // 所有编译完成之后的回调[注意小心造成递归的情况出现,也就是回调中的操作又重新引起了编译] // 如果出现编译错误,那么这个回调不会被执行 [UnityEditor.Callbacks.DidReloadScripts] private static void OnCompiled() { // Debug.ClearDeveloperConsole(); Debug.LogError(“编译成功!”); SuccsccAction?.Invoke(); } private static void Update() { if (EditorUtility.scriptCompilationFailed) { EditorApplication.update -= Update; Debug.LogError(“编译失败!”); FailAction?.Invoke(); } } }
感谢kaclok@UWA问答社区提供了回答
A2:Trick有一个,只是比较老了。思路是尝试Clear掉日志。而编译错误是Clear不掉的,因此可以判断出是否遇到了编译错误。
static void ClearLog() { Assembly assembly = Assembly.GetAssembly(typeof(SceneView)); Type logEntries = assembly.GetType("UnityEditorInternal.LogEntries"); logEntries.GetMethod("Clear").Invoke (new object (), null); int count = (int)logEntries.GetMethod("GetCount").Invoke(new object (), null); if (count > 0) throw new Exception("Cannot build because you have compile errors!"); }
UI
Q:Unity 5.6.6版本中进行UGUI打图集,发现空间够512x512,每张图的大小是101x101的,17张101却打成了512x1024的图集。
测试的图:
A1:有Padding,每边一个像素,所以大了101变成103了,512放不下了。
感谢lopezycj@UWA问答社区提供了回答A2:Sprite atlas有一个Padding属性,最小是2像素,默认是4像素。
以2像素为例,上面那张atlas图高512,四张Texture占用的高度为:2+101+2+101+2+101+2+101=412,还剩100像素,已经塞不下纵向第五行的Texture了(何况第五行和第四行之间还有2像素的Padding)。
所以一张512x512的atlas,如果要放下5行x5列的Texture,每张Texture最大只能是100x100像素,然后还要记得设置atlas的Padding属性为2像素。
今天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题也许都只是冰山一角,我们早已在UWA问答网站上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入,也许你的方法恰能解别人的燃眉之急;而他山之“石”,也能攻你之“玉”。
官网:www.uwa4d.com
官方技术博客:blog.uwa4d.com
官方问答社区:answer.uwa4d.com
官方技术QQ群:793972859(原群已满员)
封面图来源于网络
以上所述就是小编给大家介绍的《不同种Mesh的DrawCall优化策略》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 负载均衡策略之轮询策略
- 负载均衡策略之两次随机选择策略
- 深度策略梯度算法是真正的策略梯度算法吗?
- 产品策略模型方法论:谈谈我对产品策略模型的6点理解
- 重学 Java 设计模式:实战策略模式「模拟多种营销类型优惠券,折扣金额计算策略场景」
- redis 数据淘汰策略
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。