如何做好帧同步下的移动系统

如何做好帧同步下的移动系统

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

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


本期目录:

  • 如何做好帧同步下的移动系统
  • 分支管理同步问题
  • 相机截屏比较节省性能的方法
  • 如何获取当前游戏中Texture的MipMap使用等级
  • 特效合并的问题

帧同步

Q:以前自己做Demo的时候,用CharacterController和刚体来解决移动穿墙的问题,代码简单,效果也不错。但是工作需要做帧同步的射击游戏,刚体毕竟是属于显示层的东西,每台机器因为性能不同、更新频率不同,计算出来的结果也不一样,造成不同步,所以是用不了的。

目前的做法是通过Unity自己的Physics.BoxCast来做,玩家输入的时候,向输入方向投射碰撞盒,然后和障碍物碰撞并计算最远可以移动的位置。

简单的地形,效果也还可以,复杂的地形总会遇到各种各样的新问题,毕竟是自己造轮子,总会遇到很多坑。想问下有没有相关的算法、文章、论文、书籍之类的可供参考的?

表现和逻辑分离已经做到了,项目目前大量使用浮点数,但也已经开始逐渐换成定点数,也会去用定点数的物理库。关于帧同步问题,参考的文章比较多,相对比较了解了。比较不解的地方是:

1、水平移动、空中360度移动的障碍检测及角色位置处理;
2、在墙上攀爬的位置、朝向、动作的处理。

一直没找到相关的资料。

我们的项目还没有引入成熟的物理引擎,都是我自己写的算法,所以才会有这些困惑,想了下确实没有必要自己造轮子。那问题来了,各位能不能推荐些Unity可用的定点数物理引擎呢?

A1:个人觉得有两个点:

1、理想状况下,如果在逻辑层有一套完备的物理引擎和寻路系统,你列举的这些内容就自然可以做了,寻路系统可能好做一些,完备的物理引擎一般来说自己重新实现的少,基本是按照需求做具体的功能实现。

2、关于攀爬的动作处理,理论上逻辑层是不关注动作的,只关注状态,动作是表现层的事情。

看题主提的这些点,感觉题主做的游戏非常偏动作向,如果要好的操作体验,对于真正的动作游戏来说,帧同步未必是一个最好的方式,或者要加入很多提前表现和差值才能做到的好的体验。

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

A2:帧同步方案,可以参考一下 Github上的LockStepFramework,或者腾讯好像有一套帧同步解决方案对外开放,可以联系一下,看是否适合。同时就像贾伟昊说的,如果非常偏动作向, 预表现和出现误差的回滚是优秀体验比较重要的点,在设计框架的时候要提前考虑。

1、帧同步首先下需要有一套定点数库,因为不同的硬件平台,浮点数计算结果不一致的。
2、表现和逻辑一定要分离。
3、建议自己实现一套物理库。

感谢叶思源@UWA问答社区提供了回答

A3:先不管客户端做挂的情况下,可以只管自己的移动物理碰撞,其他的角色不用做碰撞。只需要按帧同步我的场景信息(位置、朝向、动作)即可,可以适当的做预测。同步信息,位置、朝向、动作(在第几帧),都必须能让时间线可以重入,这点其实很容易做到。总之,其他对象不用做碰撞,只自己计算就可以了。

还有一种方案,就是所有角色,包括自己,都采用服务器广播来做,可以做一个隐藏的角色,用于预碰撞,并把状态信息上传到服务器,再由服务器广播并显示。这样所有的信息都是可以按时间点重播了。你只需要记录下这些消息包,重新播放,并反复调整对应的策略就可以了。

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


Version Control

Q:这是一个困扰我多年的问题。

项目一测试,就要开分支。出包后,分支有问题或有新需求,就要从主干同步资源和代码过去。随着项目越来越大、功能越来越多、团队越来越大,同步就成了一个非常头疼的事情。

我们现在的开发和同步流程非常的原始:所有人开发在主干,有需要测试、上线版本时,开个分支。分支上的需求和bug在主干开发。等需要更新时,同步代码和资源到分支,重新打资源和代码包。

代码汇总到一个人、资源汇总到另一个人。所有功能开发相关的人都在一个“同步群”,每个人把要同步的内容按固定格式发到群里。开发完成,等真正要同步的时候,这两个负责同步的人会按大家发的同步内容一点一点地同步。

这样做的问题很明显:

1、同步总是那两个人,一个是客户端负责人,另一个是管理同步的PM,大材小用。而且代码都是摘同,每次同步都要大半天的时间,那么多代码要同步,时间长了看着眼都疼。

2、容易出错:
a、对于同步的人:同步的人和开发的人不是同一个人,同步容易出错。
b、对于开发的人:有些内容早就开发完了,需要同步的时候已经不记得要同步什么,还得回头去找,也容易出错。

大家有没有遇到同样的困扰?有什么更优的流程吗?希望大家能给点建议,或者简单的说一下自己项目的流程,多谢!

A:我们的git流程:
1、不再使用master,因为整个持续开发的过程中基本上不存在什么需要master的时候;
2、主要开发分支为dev,所有经测试的新功能都合入dev;
3、每个人按功能和职责分到尽可能细但是要完整的若干feature,在自己本地建立feature分支进行开发。每个人可以由若干多个feature同时进行,但是不建议太多,否则管理难度上升。尽量不上传本地开发分支到服务器,避免服务器上出现太多中间过程的分支。除非该feature时间跨度长或者需要多人协作;
4、开发feature过程中要择机(每天或者一些关键节点)将dev合入自己的feature分支,保证自己分支功能最新,冲突最少;
5、当feature开发完成,并且需要发布时则走dev->feature->dev这样的合并流程,将feature合并到dev;
6、保留合并后的feature一段时间,以便之后修改回滚等,一段时间后(往往是功能上线后)删除本地feature分支,避免分支越来越多;
7、当要发布时,将本次需要发布每个人手头的feature逐一按5的方式合并到dev,然后开始测试,内网测试通过后,从该dev开出新branche,名字取预定的本次发布日期,然后在这个分支上继续进行外网测试和bug修补;
8、发布用branche上发现并修正的bug,由该问题的开发者合并回dev,往往用cherry-pick,其他人继续在dev和自己的feature分支做开发;
9、关于资源,一般我们面向功能开发,不会分专人来分开管理资源,所以功能开发者需要完全管理掌握该功能相关的所有资源和代码,他要负责资源和代码的上传同步问题的解决;
10、尽可能将权限和流程都分下去,做到每个项目开发者都熟练使用。允许出错,在出错中学习。当每个人都能走通流程的情况下可以避免因为人员变化造成作业中断的情况。

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


Render

Q:目前项目中需要一个相机一秒30次的截图,但是用ReadPixels函数一秒30次的调用太消耗性能,请问有没有可以代替它的方法,或者有没有其他相机截屏比较节省性能的方法,跪谢了!

A:对于比较新的版本,Unity有一个AsyncGPUReadback的功能,可以帮助截图,比ReadPixels要快,但每秒30次,还是有很大开销。

可以查看这个开源库示例:
https://lab.uwa4d.com/lab/5b5a5659d7f10a201fe4c4e0

如果是想截图之后输出保存在外部,对于Windows平台而言,有一个更快的方式截取全屏:Desktop Duplication 抓屏技术。这个速度非常快,几乎和录像一样。

可以查看这个开源库示例:
https://lab.uwa4d.com/lab/5b563fb5d7f10a201fd8d0de

该回答由UWA提供,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5cef9b3bd2751137709826fe


Texture

Q:想要得到当前一张贴图的MipMap使用level,Unity 2017.4没有对应的API,有什么其他办法可以得到呢?

A:渲染时使用的MipMap层级是逐像素不同的,而不是逐Texture的。所以应该在Shader的fragment阶段才有可能拿到这个吧。AssetStore上有一些显示MipMap的工具,我之前看都是估算的。Unity自己带的那个Scene View下的模式不知道具体是怎么计算的,能找到源码的情况下可以参考一下,检索下应该是可以找到方法的。具体我没做过,但是感觉方向是根据ddx和ddy来计算。

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


DrawCall

Q:像这种特效,4个节点,每个节点用了一个材质球、一张贴图,这样就相当于有4 DrawCall。

请输入图片描述

由于是同一个Shader,所以我考虑合并起来,但是我们的贴图可能其他特效也用到了,相当于这部分贴图如果我们合并到一张Atlas上就会存在冗余,不合并DrawCall 高,合并内存高。想问下大家遇到这种情况有什么好的建议吗?特别是特效方面的。

A:“我们的贴图可能其他特效也用到了,相当于这部分贴图如果我们合并到一张Atlas上就会存在冗余”,一般你们的特效贴图是什么尺寸呢?小的话可以考虑一张图集多合并几个特效,比如把共用贴图的,而且会做预加载的合并在一起,做下依赖打包。

另外最好可以先获取一些数据来帮助决策:比如,战斗中特效部分的DrawCall和内存情况,总的DrawCall和内存情况。评估下当前是DrawCall比较吃紧,还是内存比较吃紧。

该回答由UWA提供,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5ce757169b1cb2656d106abe


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

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

封面图来自网络