不同种Mesh的DrawCall优化策略

不同种Mesh的DrawCall优化策略

1)不同种Mesh的DrawCall优化策略
2)AnimationClip内存优化
3)渲染效果出错
4)Unity编译后报错是否有回调可用
5)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改写一下也不难。

感谢Nil@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5cb8ca65e08a260abaf02053


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等。

感谢郑骁@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5cb856d5e08a260abaf02026


渲染

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里就解决了。

感谢贤@UWA问答社区分享了该问答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5cb463723ded097520c24cea


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!");
     }

感谢张锐@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5cc1190f5dad710abee80429


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问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5cbf1d175dad710abee80409


今天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题也许都只是冰山一角,我们早已在UWA问答网站上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入,也许你的方法恰能解别人的燃眉之急;而他山之“石”,也能攻你之“玉”。

官网:www.uwa4d.com
官方技术博客:blog.uwa4d.com
官方问答社区:answer.uwa4d.com
官方技术QQ群:793972859(原群已满员)


这是第156篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题,建议阅读时间10分钟,认真读完必有收获。

UWA 问答社区:answer.uwa4d.com
UWA QQ群2:793972859(原群已满员)

封面图来源于网络