【厚积薄发】Lua与C#之间的穿梭问题

【厚积薄发】Lua与C#之间的穿梭问题_第1张图片
image

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

UWA QQ群:465082844(仅限技术交流)

脚本

Q:Lua与C#之间的调用频率是影响Lua性能很重要的因素,最近我们的项目也在分析这类问题。****如何统计Lua与C#之间调用的次数呢?我****感觉要注入的代码有点多,我们写了大量的warp代码,每个都添加有点不现实,而且warp代码都是自动生成的。大家有什么好建议吗?

我们项目用的是ToLua,Unity版本是5.6.1p1。

A1:Lua调用C#用debug.sethook。云风有一个基于这个方法写的工具cloudwu/luaprofiler,不过不能直接拿来用,需要自己编库。

除了这个以外,直接在Lua里面挂上也是可以的,比较影响性能。C#调用Lua看LuaFunction。

感谢凯奥斯@UWA问答社区提供了回答

A2:Lua和C#之间的调用次数统计的工具,只需要修改一下ToLua导出warp接口的地方就好了,重新生成一次代码,加上宏或者条件编译的控制,就可以很方便地做到即可以在编辑器模式下做次数统计,又可以不影响发布到设备上的过程。

生成的代码可以自己添加tag,用于统计,比如我们的一个调用代码:

【厚积薄发】Lua与C#之间的穿梭问题_第2张图片
image

UWA在UWA Day上展示的过程就更简单,直接封装成函数,通过[Conditional(“XXX”)]来控制就好了。

如果要统计C#反向调用Lua的地方,LuaFunction的几个Call函数是一个切入点。

**********感谢贾伟昊@UWA问答社区提供了回答**********

********欢**迎大家转至社区进行进一步交流**********

动画

Q:为了动画重用减少资源重复的问题,我们采用人性形动画格式来制作。因为有第一人称,手掌手腕是处于特写状态下的,所以任何瑕疵都会暴露无遗。为了避免手腕扭曲变形的瑕疵,我们添加了附加骨骼来解决问题,骨骼的位置和结构关系如下图:

【厚积薄发】Lua与C#之间的穿梭问题_第3张图片
image

Unity中没有添加附加骨骼的手腕旋转效果:

【厚积薄发】Lua与C#之间的穿梭问题_第4张图片
image

Unity中添加了前臂附加骨骼的手腕旋转效果问题1:手腕和手臂交界处有错位现象

【厚积薄发】Lua与C#之间的穿梭问题_第5张图片
image

Max中添加了前臂附加骨骼的手腕旋转效果(可以看出手腕扭曲完美解决,但是在Unity中效果不理想)

【厚积薄发】Lua与C#之间的穿梭问题_第6张图片
image

问题2:人形动画格式大拇指的动画就是没办法还原,总是敲着的,我们检查过骨骼匹配问题,如下图都是正常的,就是大拇指没办法弯曲。

【厚积薄发】Lua与C#之间的穿梭问题_第7张图片
image
【厚积薄发】Lua与C#之间的穿梭问题_第8张图片
image

A:Unity的人形骨骼这里在使用的时候有不少小坑,而官方文档很多地方写得很隐晦,我们项目在用人形骨骼,在用Retargeting的时候也是各种动作有小问题。

先说一下我们自己得出的一些结论吧:

1)角色自己的动画,使用自己的Avatar,人形骨骼应该是可以做到和Max以及Generic的方式的动画完全一样的效果;

2)如果是别的骨骼,有体型上的差异,比如身高、肩宽等,经过Retargeting的效果之后,可以做到整体效果是正确的,但是因为累积误差的原因,距离根骨骼比较远的骨骼,比如脚、手指等位置,会有微小的差异,比如脚不够贴地、idle动作脚部有微小的抖动现象等等。

Retargeting的原理我之前写过一篇文章《动画重定向技术分析及其在Unity中的应用》,有兴趣可以看看。这里补充一些后来我们自己在使用的时候发现的点。Unity中有几个文件,他们记录的信息分别有:

1)Avatar文件,就是所谓的骨骼文件,这里记录了用于Retargeting的基本的T-pos信息,Unity中定义的是一个大T的姿势,而Max里常用的可能是一个小T姿势,所以这里要做一些调整,细节后面来说;

2)动画文件,记录动画差异信息。导入的动画文件在使用人形骨骼的情况下会需要指认Avtar的引用到所对应的文件上,如果Avatar有修改,动画文件需要进行Update操作,这个过程是重新计算差异的过程。我们观察到,这个动画文件的内容,和导入动画文件的Max文件里的T-pos姿势有很强的相关性。

如果你看了之前的文章,那这里就比较好理解了。我们有两套骨架,A、B,需要把B的动作应用到A上,那需要四个数据:

A的T-pos信息;

B的T-pos信息;

B的动画信息;

A的动画信息 = B的动画信息 - B的T-pos信息 + A的T-pos信息。

所以前面说的动画文件里的信息,其实应当理解为B的动画文件和B的T-pos的差异。(这里说得有点绕,先埋个坑吧,等我有时间了详细整一篇博客好了。)

所以我们项目给到美术的建议是:导出Avatar的T-pos和导出动画的Max文件里的T-pos信息要一致,这样才能做到动作尽量的还原。(所以你可以测试下,使用同一个Max文件导出的动画和Avatar,在Unity里应当和Max里是完全一致的才对。)

说了半天原理,也是说上述的一些问题可能需要题主自己来根据原理推测并解决。当然还是要说下我对于这两个问题的想法。

第一个手腕扭曲的问题,说实话我貌似遇到过,但是时间有点久远,具体的细节不太清楚了,建议题主查看下几个方向:

是否非人形骨骼也有这个问题?

是否可能是蒙皮的问题,或者通过修改蒙皮来解决?

是否是人形骨骼Avatar里的手腕的骨骼映射关系存在问题,通过调整Avatar的姿势是否可能缓解这个问题?

第二个手指不动的问题,可能需要确认下Avatar里的姿势手指是否和预期不一样,这种情况可以通过给动作中的手指一个很夸张的姿势来查看,如果真的是完全没有动作的话,查看下动作中是否mask的设置有遗漏?

动作这块是需要程序和动作美术一起不断测试,才能找到一个好的平衡点。我自己是Max不够熟悉,所以看问题的时候还要拉着美术一起。

********感谢贾伟昊@UWA问答社区提供了回答,欢**迎大家转至社区进行进一步交流**********

动画

Q:动画片段的数量对性能开销是否有影响?若有,对同一个动画片段,不同层级的多处复用是否也是有影响?(动画控制器游戏过程中没有激活和隐藏操作,不清楚动画片段数据的采样和读取消耗为何会偏高)

A1:动画说白了就是变换而已,平移、旋转和缩放。每一帧将变换矩阵乘到各个顶点上,而这部分是纯CPU计算。

那么与性能开销相关的就是:顶点数量、骨骼数量、层的数量。

另外一个就是BoneWeight了,weight(n)的非零个数越多,每一帧顶点的变换计算也就越多。

所以可以优化的点:1)减面2)减少骨骼3)精简层4)减少骨骼blend数量另外对于动画所占内存的优化,可以参考文章:Unity动画文件优化探究

感谢凯奥斯@UWA问答社区提供了回答

UWA:除了process animation, 动画片段数量也会对animatorcontorller的维护带来开销(反映在writejob上):"when using the Animator, all the properties of all the clips currently connected are written, whether the clips are playing or not. "

********欢**迎大家转至社区进行进一步交流**********

粒子系统

Q:当场景中有大量的环境粒子系统,针对粒子系统做过裁剪优化,请问粒子系统在远离相机后怎么正确的进行休眠,把粒子系统进行stop就行了吗?会对渲染或CPU还有没有多余的开销?还是只能把粒子系统根节点的gameobject的active设置为False?

UWA:建议通过Active和Deactive来进行控制,未Deactive的Particle System一样会参与计算,比如渲染模块中的Culling等等。同时,Active/Deactive对于粒子系统对于粒子系统的处理一般都不耗时。

********该回答由UWA提供,欢**迎大家转至社区进行进一步交流**********

代码

Q:我在使用Deep Profile查找代码性能时,发现一个列表查找每次Find()都会产生2.5KB GC Alloc,然后我改变了一下写法,不用Find(),直接for循环遍历,发现GC Alloc没了,耗时几乎一样。然后我去查找了Find()的IL,也没觉得哪里会产生GC,请大家指教。

A:

【厚积薄发】Lua与C#之间的穿梭问题_第9张图片
image
【厚积薄发】Lua与C#之间的穿梭问题_第10张图片
image
【厚积薄发】Lua与C#之间的穿梭问题_第11张图片
image
【厚积薄发】Lua与C#之间的穿梭问题_第12张图片
image

我猜测题主的代码里是类似下面的这种逻辑:在一个循环里,多次执行了Find操作,Find的参数(闭包函数)使用了每次循环都会变化的non-local变量,因此产生了较多的GC。这种方式产生GC的原因是,每次循环会new一个委托对象。

********感谢Walker@UWA问答社区提供了回答,**大家可转至社区进行进一步交流**********

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

你可能感兴趣的:(【厚积薄发】Lua与C#之间的穿梭问题)