游戏蛮牛学习群(纯技术交流,不闲聊):159852603
游戏蛮牛 手机端
开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

开发者专栏

关注:2292

当前位置:游戏蛮牛 技术专区 开发者专栏

__________________________________________________________________________________
开发者干货区版块规则:

  1、文章必须是图文形式。(至少2幅图)
      2、文章字数必须保持在1500字节以上。(编辑器右下角有字数检查)
      3、本版块只支持在游戏蛮牛原创首发,不支持转载。
      4、本版块回复不得无意义,如:顶、呵呵、不错......【真的会扣分的哦】
      5、......
__________________________________________________________________________________
查看: 2297|回复: 35
发新帖

[士郎] 帧同步联机战斗(预测,快照,回滚)

[复制链接]  [移动端链接]
排名
3
昨日变化

6691

主题

7213

帖子

2万

积分

Rank: 16

UID
1231
好友
185
蛮牛币
9154
威望
30
注册时间
2013-7-29
在线时间
3445 小时
最后登录
2018-8-24

社区QQ达人活力之星原创精华达人突出贡献奖财富之证游戏蛮牛QQ群会员蛮牛妹VIP

跳转到指定楼层
楼主
发表于 2018-8-13 14:05:34 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
终于要写帧同步这块了,这块很难讲清楚,细枝末节有很多优化点,也有一些不同的优化方向,根据不同项目类型,对操作手感的要求,对联机玩家的个数等,会有不同的难点和痛点。不同的优化方向,优化手法的差异,可能导致一些争论。并且,帧同步,本身也有很多变种,以应对不同的需求。所以,我一切都是基于我们的项目类型(ACT)来做的方案和优化,并不一定适合其它也需要帧同步的游戏,故在此提前说一下,以免引起一些不必要的误解。
有些东西,可能会写得详细些,有些可能会简略些,不可能照顾到所有程度的读者,见谅。
帧同步的几个难点
帧同步的基础原理,以及和状态同步的区别,已经有很多文章介绍,我就不再赘述,大家可以自行google。以下只说几个难点。
  • 保证客户端独自计算的正确,即一致性


帧同步的基础,是不同的客户端,基于相同的操作指令顺序,各自执行逻辑,能得到相同的效果。就如大家所知道的,在unity下,不同的调用顺序,时序,浮点数计算的偏差,容器的排序不确定性,coroutine内写逻辑带来的不确定性,物理浮点数,随机数值带来的不确定性等等。
有些比较好解决,比如随机数值,只需要做随机种子即可。
有些注意代码规范,比如在帧同步的战斗中,逻辑部分不使用Coroutine,不依赖类似Dictionary等不确定顺序的容器的循环等。
还有最基础的,要通过一个统一的逻辑tick入口,来更新整个战斗逻辑,而不是每个逻辑自己去Update。保证每次tick都从上到下,每次执行的顺序一致。
物理方面,因为我们战斗逻辑不需要物理,碰撞都是自己做的碰撞逻辑,所以,跳过不说,这块可以参考别的文章。
最后,说一下,浮点数计算无法保证一致性,我们需要转换为定点数。关于定点数的实现,比较简单的方式是,在原来浮点数的基础上乘1000或10000,对应地方除以1000或10000,这种做法最为简单,再辅以三角函数查表,能解决一些问题,减少计算不一致的概率,但是,这种做法是治标不治本的方式,存在一些隐患(举个例子,例如一个int和一个float做乘法,如果原数值就要*1000,那最后算出来的数值,可能会非常大,有越界的风险。)。
最佳的解决办法,是使用实现更加精确和严谨,并经过验证的定点数数学库,在c#上,有一个定点数的实现,Photon网络的早期版本,Truesync有一个很不错的定点数实现

定点数的实现
其中FP,就可以完全代替float,我们只需要将我们自己的逻辑部分,float等改造为FP,就可以轻松解决。并且,能够很好的和我们protobuf的序列化方式集成(注意代码中的Attribute,如下图),保证我们的配置文件,也是定点数的。





TSVector对应Vector3,只要基于FP,可以自己扩展自己的数据结构。(当然,如果用到了复杂的插件,并且不开源,那么对于定点数的改造,就会困难很多)



三角函数通过查表方式实现,保证了定点数的准确
我个人认为,这一套的实现,是优于简单的乘10000,除10000的方式。带来的坏处,可能就是计算性能略差一点点,但是我们大量测试下来,对计算性能的影响很小,应该是能胜任绝大部分项目的需求。


对于计算的不确定性,我们也有一些小的隐患,就是,我们用到了Physics.Raycast来检测地面和围墙,让人物可以上下坡,走楼梯等高低不平的路,也可以有形状不规则的墙。这里会获得一个浮点数的位置,可能会导致不确定性,这里,我们用了数值截断等方式,尽量规避,经过反复测试,没有出现过不一致。但是这种方式,毕竟在逻辑上,存在隐患,更好的方式,是实现一套基于定点数的raycast机制,我们人力有限,就没时间精力去做了。


  • 帧同步网络协议的实现


在处理好了基础的计算一致性问题后,我们就要考虑网络如何通信。这里,我不谈p2p方式了,我们以下谈的,都是多client,一个server的模式,server负责统一tick,并转发client的指令,通知其他client


首先,是网络协议的选择。TCP和UDP的选择,我就不多说了,帧同步肯定要基于UDP才能保证更低的延迟。在UDP的选择上,我看网上有些文章,容易导入一个误区,即,我们是要用可靠传输的UDP,还是冗余信息的UDP。


基于可靠传输的UDP,是指在UDP上加一层封装,自己去实现丢包处理,消息序列,重传等类似TCP的消息处理方式,保证上层逻辑在处理数据包的时候,不需要考虑包的顺序,丢包等。类似的实现有Enet,KCP等。


冗余信息的UDP,是指需要上层逻辑自己处理丢包,乱序,重传等问题,底层直接用原始的UDP,或者用类似Enet的Unsequenced模式。常见的处理方式,就是两端的消息里面,带有确认帧信息,比如客户端(C)通知服务器(S)第100帧的数据,S收到后通知C,已收到C的第100帧,如果C一直没收到S的通知(丢包,乱序等原因),就会继续发送第100帧的数据给S,直到收到S的确认信息。



有些文章介绍的时候,没有明确这两者的区别,但是这两种方式,区别是巨大的。可靠传输的UDP,在帧同步中,个人认为是不合适的,因为他为了保证包的顺序和处理丢包重传等,在网络不佳的情况下,delay很大,将导致收发包处理都会变成类似tcp的效果,只是比TCP会好一些。必须要用冗余信息的UDP的方式,才能获得好的效果。并且实现并不复杂,只要和服务器商议好确认帧和如何重传即可,自己实现,有很大的优化空间。例如,我们的协议定义类似如下:




双方都要通知对方,已经接受哪一帧的通知了,并通过cmd list重发没有收到的指令
这里简单说一下,对于这种收发频繁的消息,如果使用protobuf,会造成每个逻辑帧的GC,这是非常不好的,解决方案,要么对protobuf做无GC改造,要么就自己实现一个简单的byte[]读写。无GC改造工程太大,感觉无必要,我们只是在战斗的几个频繁发送的消息,需要自己处理一下byte[]读写即可

------------------------------------
  • 逻辑和显示的分离


这块很多讲帧同步的文章都提过了。我在前面讲技能编辑器的时候,也提过,配置的数据和显示要分离,在战斗中,战斗的逻辑,也要和显示做到分离。
例如,最基本,我们动作切换的逻辑,是基于自己抽象的逻辑帧,而不是基于animator中一个clip的播放。比如一个攻击动作,当第10帧的时候,开始出现攻击框,并开始检测和敌人受击框的碰撞,这个时候的第10帧,必须是独立的逻辑,不能依赖于animator播放的时间,或者AnimatorStateInfo的normalizedTime等。甚至,当我们不加载角色的模型,一样可以跑战斗的逻辑。如果抽离得好,还可以放到服务器跑,做为战斗的验证程序,王者荣耀就是这样做的。



  • 联机如何做到流畅战斗


前面所有的准备,最终的目的,都是为了战斗的流畅。特别是我们这种Act游戏,或者格斗类游戏,对按键以后操作反馈的即时性,要求非常高,一点点延迟,都会影响玩家的手感,导致玩家的连招操作打断,非常影响体验。我们对延迟的敏感性,甚至比MOBA类游戏还要高,我们要做到好的操作手感,还要联机战斗(PVP,组队PVE),都需要把帧同步做到极致,不能因为延迟卡住或者操作反馈出现变化。



因为这个原因,我们不能用lockstep的方式,lockstep更适合网络环境良好的内网,或者对操作延迟不敏感的类型(例如我听过还有项目用来做卡牌类的帧同步)。



我们也不能用缓存服务器确认操作的方式,也就是一些游戏做的指令buffer。这个模式能解决一些小的网络波动,对一些操作反馈不需要太高的游戏,例如有些游戏攻击前会有一个比较长的前摇动作,这类游戏,用这种方式,应该就能解决大部分问题。但是这种方式还是存在隐患,即使通过策略能很好地动态调整buffer,也还是难以解决高延迟下的卡顿和不流畅。王者荣耀优化得很好,他们说能让buffer长度为0,文章只提到通过平滑插值和逻辑表现分离来优化,更细节的没有提到,我不确定他们是否只是基于这个方式来优化的。目前也没有看到更具体的分析。



指令buffer的方式,也不能满足我们的需求,或者说,我没有找到基于此方式,能优化到王者荣耀的效果的办法。我也测试过其他moba和act,arpg类游戏的联机,在高延迟,网络波动情况下,没有比王者表现更好的了。


最后,在仔细研究了我们的需求后,找到一篇指导性的文章,非常适合我们。

就是Understanding Fighting Game Networking,这篇文章非常详细地介绍了各种方式,最终回滚逻辑(rollback)是终极的解决方案,国内也有文章提到过,即Skywind Inside " 再谈网游同步技术里面提到的Time Warp方式,我理解回滚逻辑,和Time Warp是一个概念。


  • 游戏逻辑的回滚


回滚逻辑,就是我们解决问题的方案。可以这样理解,客户端的时间,领先服务器,客户端不需要服务器确认帧返回才执行指令,而是玩家输入,立刻执行(其他玩家的输入,按照其最近一个输入做预测,或者其他更优化的预测方案),然后将指令发送给服务器,服务器收到后给客户端确认,客户端收到确认后,如果服务确认的操作,和之前执行的一样(自己和其他玩家预测的操作),将不做任何改变,如果不一样(预测错误),就会将游戏整体逻辑回滚到最后一次服务器确认的正确帧,然后再追上当前客户端的帧。



此处逻辑较为复杂,我尝试举个例子说明下。


当前客户端(A,B)执行到100帧,服务器执行到97帧。在100帧的时候,A执行了移动,B执行了攻击,A和B都通知服务器:我已经执行到100帧,我的操作是移动(A),攻击(B)。服务器在自己的98帧或99帧收到了A,B的消息,存在对应帧的操作数据中,等服务器执行到100帧的时候(或提前),将这个数据广播给AB。


然后A和B立刻开始执行100帧,A执行移动,预测B不执行操作。而B执行攻击,预测A执行攻击(可能A的99帧也是攻击),A和B各自预测对方的操作。
在A和B执行完100帧后,他们会各自保存100帧的状态快照,以及100帧各自的操作(包括预测的操作),以备万一预测错误,做逻辑回滚。
执行几帧后,A,B来到了103帧,服务器到了100帧,他开始广播数据给AB,在一定延迟后,AB收到了服务器确认的100帧的数据,这时候,AB可能已经执行到104了。A和B各自去核对服务器的数据和自己预测的数据是否相同。例如A核对后,100帧的操作,和自己预测的一样,A不做任何处理,继续往前。而B核对后,发现在100帧,B对A的预测,和服务器确认的A的操作,是不一样的(B预测的是攻击,而实际A的操作是移动),B就回滚到上一个确认一样的帧,即99帧,然后根据确认的100帧操作去执行100帧,然后快速执行101~103的帧逻辑,之后继续执行104帧,其中(101~104)还是预测的逻辑帧。
因为客户端对当前操作的立刻执行,这个操作手感,是完全和pve(不联网状态)是一样的,不存在任何delay。所以,能做到绝佳的操作手感。当预测不一样的时候,做逻辑回滚,快速追回当前操作。


这样,对于网络好的玩家,和网络不好的玩家,都不会互相影响,不会像lockstep一样,网络好的玩家,会被网络不好的玩家lock住。也不会被网络延迟lock住,客户端可以一直往前预测。


对于网络好的玩家(A),可以动态调整(根据动态的latency),让客户端领先服务器少一些,尽量减少预测量,就会尽量减少回滚,例如网络好的,可能客户端只领先2~3帧。


对于网络不好的玩家(B),动态调整,领先服务器多一些,根据latency调整,例如领先5帧。
那么,A可能预测错的情况,只有2~3帧,而网络不好的B,可能预测错误的帧有5帧。通过优化的预测技术,和消息通知的优化,可以进一步减少A和B的预测错误率。对于A而言,战斗是顺畅的,手感很好,少数情况的回滚,优化好了,并不会带来卡顿和延迟感。



重点优化的是B,即网络不好的玩家,他的操作体验。因为客户端不等待服务器确认,就执行操作,所以B的操作手感,和A是一致的,区别只在于,B因为延迟,预测了比较多的帧,可能导致预测错,回滚会多一些。比如按照B的预测,应该在100帧击中A,但是因为预测错误A的操作,回滚重新执行后,B可能在100帧不会击中A。这对于B来说,通过插值和一些平滑方式,B的感受是不会有太大区别的,因为B看自己,操作自己都是及时反馈的,他感觉自己是平滑的。
这种方式,保证了网络不好的B的操作手感,和A一致。回滚导致的一些轻微的抖动,都是B看A的抖动,通过优化(插值,平滑等),进一步减少这些后,B的感受是很好的。我们测试在200~300毫秒随机延迟的情况下,B的操作手感良好。


这里,客户端提前服务器的方式,并且在延迟增大的情况下,客户端将加速。

这里,我要强调的一点是,我们这里的预测执行,是真实逻辑的预测,和很多介绍帧同步文章提到的预测是不同的。有些文章介绍的预测执行,只是view层面的预测,例如前摇动作和位移,但是逻辑是不会提前执行的,还是要等服务器的返回。这两种预测执行(View的预测执行,和真实逻辑的预测执行)是完全不是一个概念的,这里需要仔细地区分。


这里有很多的可以优化的点,我就不一一介绍了,以后可能零散地再谈。


  • 游戏逻辑的快照(snapshot)


我们的逻辑之所以能回滚,都是基于对每一帧状态可以处理快照,存储下每一帧的状态,并可以回滚到任何一帧的状态。在Understanding Fighting Game Networking 文章和守望先锋网络 文章中,都一笔带过了快照的说明。他们说的快照,可能略有不同,但是思路,都是能保存下每一帧的状态。如果去处理快照(Understanding那篇文章做的是模拟器游戏,可以方便地以内存快照的方式来做),是一个难点,这也是我前面文章提到ECS在这个方式下的应用,云风的解释:



ECS是一个好的处理方式,并且我找到一篇文章,也这样做了(我看过他开源的demo,做得还不够好,应该还是demo阶段,不太像是一个成型的项目)。这篇文章的思路是很清晰的,并且也点到了一些实实在在的痛点,解决思路也基本是正确的,可以参看。


这块,我做得比较早了,当时守望先锋的文章还没出,我的战斗也没有基于ECS,所以,在处理快照上,只有自己理顺逻辑来做了。
我的思路是,通过一个回滚接口,需要数据回滚的部分,实现接口,各自处理自己的保存快照和回滚。就像我们序列化一个复杂的配置,每个配置各自序列化自己的部分,最终合并成一个序列化好的文件。


首先,定义接口,和快照数据的reader和writer





然后,就是每个模块,自己去处理自己的takeSnapshot和rollback,例如:

简单的数值回滚


复制的列表回滚和调用子模块回滚


思路理顺以后,就可以很方便地处理了,注意write和read的顺序,注意处理好list,就解决了大部分问题。当然,在实现逻辑的过程中,时刻要注意,一个模块如何回滚(例如获取随机数也需要回滚)。


有一个更简单的方式,就是给属性打Attribute,然后写通用的方法。例如,我早期的实现方案:

给属性打标签
根据标签,通用的读写方法,通过反射来读写,就不需要每个模块自己去实现自己的方法了:

部分代码
这种方法,能很好地解决大部分问题,甚至前面提到的Truesync,也是用的这种方式来做。


但是这种方法有个难以回避的问题,就是GC,因为基于反射,当我们调用field的GetValue和SetValue的时候,GC难以避免。并且,因为全自动,不方便处理一些特殊逻辑,调试优化也不方便,最后改成了现有的方式,虽然看起来笨重一些,但是可控性更强,我后续做的很多优化,都方便很多。


关于快照,也有很多可以优化的点,无论是GC内存上的,还是运行效率上的,都需要优化好,否则,可能带来性能问题。这块优化,有空另辟文章再细谈吧。
当我们有了快照,就可以支持回滚,甚至跳转。例如我们要看战斗录像,如果没有快照,我们要跳到1000帧,就需要从第一帧,根据保存的操作指令,一直快速执行到1000帧,而有了快照,可以直接跳到1000帧,不需要执行中间的过程,如果需要在不同的帧之间切换,只需要跳转即可,这将带来巨大的帮助。


  • 自动测试


由于帧同步需要测试一致性的问题,对我们来说,回滚也是需要大量测试的问题。自动测试是必须要做的一步,这块没有什么特别的点,主要就是保存好操作,快照,log,然后对不同客户端的数据做比对,找到不同的地方,查错改正。
我们现在做到,一步操作,自动循环战斗,将每一盘战斗数据上传内网log服务器。
当有很多盘战斗的数据后,通过工具自动解析比对数据,找到不同步的点。也是还可以优化得更好,只是现在感觉已经够用了。经过大量的内部自动测试,目前战斗的一致性,是很好的。



  • 总结


我们现在的帧同步方案,总结下来,就是预测,快照,回滚。当把这些有机地结合起来,优化好,就有了非常不错的帧同步联网效果,无论网络速度如何,只要不是延迟大到变态,都保证了非常好的操作手感。

快照回滚的方式,也不是所有游戏都适用



如图所述,这种模式不适合太多人的联网玩法,例如MOBA,可能就不太适用。我们最多三人联机,目前优化测试下来,效果也没有太大问题。但是联机人数越多,预测操作的错误可能性越大,导致的回滚也会越多。


一篇文章,难以讲得面面俱到,很多地方可能描述也不一定明确,并且,个人能力有限,团队人员有限(3个客户端)的情况下,必定有很多设计实现不够好的地方,大家见谅。后续有空,再补充一些细节和优化等,这里同样是希望抛砖引玉,希望看到更多好的方案。




最后啰嗦一句,如最开始所述,帧同步有很多变种和实现方式,优化方向。有时候,可能不同文章提到帧同步这个术语的时候,里面的意思,可能都有区别,大家需要仔细理清和区分。


知乎@Gordon



跟我念“站长妹纸萌萌哒!”我说站长,你说YO!爱你们么么哒~
回复

使用道具 举报

3偶尔光临
266/300
排名
11583
昨日变化
10

0

主题

38

帖子

266

积分

Rank: 3Rank: 3Rank: 3

UID
56671
好友
1
蛮牛币
442
威望
0
注册时间
2014-11-20
在线时间
152 小时
最后登录
2018-8-13
沙发
发表于 2018-8-13 15:10:53 | 只看该作者
获益匪浅,不过能不能给一些,帧同步相关的好文章
[发帖际遇]: lyxcrazy 发帖时在路边捡到 1 蛮牛币,偷偷放进了口袋. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

4四处流浪
358/500
排名
7422
昨日变化
145

1

主题

113

帖子

358

积分

Rank: 4

UID
238064
好友
1
蛮牛币
718
威望
0
注册时间
2017-9-7
在线时间
86 小时
最后登录
2018-8-25
板凳
发表于 2018-8-13 15:45:57 | 只看该作者
讲真的,这个帖子好详细啊!学习学习!!!
[发帖际遇]: 风停云晓 在论坛发帖时没有注意,被小偷偷去了 1 蛮牛币. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

6蛮牛粉丝
1091/1500
排名
2605
昨日变化
2

0

主题

284

帖子

1091

积分

Rank: 6Rank: 6Rank: 6

UID
135463
好友
0
蛮牛币
145
威望
0
注册时间
2016-1-23
在线时间
301 小时
最后登录
2018-8-22
地板
发表于 2018-8-13 15:59:23 | 只看该作者
gfvbhnvghfghsdfzsfawwdfsafdxzf

回复 支持 反对

使用道具 举报

6蛮牛粉丝
1218/1500
排名
1884
昨日变化
4

0

主题

339

帖子

1218

积分

Rank: 6Rank: 6Rank: 6

UID
87577
好友
0
蛮牛币
3968
威望
0
注册时间
2015-3-31
在线时间
213 小时
最后登录
2018-8-25
5#
发表于 2018-8-14 08:26:25 | 只看该作者
too good too strong!

回复 支持 反对

使用道具 举报

5熟悉之中
641/1000
排名
7733
昨日变化
152

0

主题

384

帖子

641

积分

Rank: 5Rank: 5

UID
254705
好友
0
蛮牛币
534
威望
0
注册时间
2017-11-16
在线时间
109 小时
最后登录
2018-8-24
6#
发表于 2018-8-14 08:34:37 | 只看该作者
66666666666666666666666666666666666

回复 支持 反对

使用道具 举报

5熟悉之中
768/1000
排名
3418
昨日变化
3

10

主题

170

帖子

768

积分

Rank: 5Rank: 5

UID
8041
好友
2
蛮牛币
996
威望
0
注册时间
2013-11-14
在线时间
184 小时
最后登录
2018-8-21

社区QQ达人

7#
发表于 2018-8-14 10:08:39 | 只看该作者
这个帖子应该是比较靠谱的帖子了!是实操过的!

回复 支持 反对

使用道具 举报

3偶尔光临
179/300
排名
37467
昨日变化
40

0

主题

33

帖子

179

积分

Rank: 3Rank: 3Rank: 3

UID
119581
好友
0
蛮牛币
180
威望
0
注册时间
2015-8-25
在线时间
140 小时
最后登录
2018-8-20
8#
发表于 2018-8-14 10:34:48 | 只看该作者
写的不错,感谢分享。
[发帖际遇]: 幸福344144 被钱袋砸中进医院,看病花了 2 蛮牛币. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

排名
913
昨日变化
3

16

主题

1105

帖子

3051

积分

Rank: 9Rank: 9Rank: 9

UID
68430
好友
12
蛮牛币
10869
威望
0
注册时间
2015-1-14
在线时间
814 小时
最后登录
2018-8-24
9#
发表于 2018-8-14 11:15:03 | 只看该作者
刚刚离开的公司项目,就是我刨坑,研究,帧同步这些,楼主总结的可以,点赞~~

回复 支持 反对

使用道具 举报

7日久生情
2631/5000
排名
466
昨日变化

1

主题

317

帖子

2631

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
27816
好友
3
蛮牛币
8456
威望
0
注册时间
2014-6-3
在线时间
853 小时
最后登录
2018-8-24
10#
发表于 2018-8-14 11:41:38 | 只看该作者
先收藏一下,
[发帖际遇]: 一个袋子砸在了 落地烟花 头上,落地烟花 赚了 1 蛮牛币. 幸运榜 / 衰神榜

回复

使用道具 举报

5熟悉之中
511/1000
排名
5062
昨日变化
31

0

主题

71

帖子

511

积分

Rank: 5Rank: 5

UID
2623
好友
0
蛮牛币
953
威望
0
注册时间
2013-8-26
在线时间
178 小时
最后登录
2018-8-25
11#
发表于 2018-8-14 11:57:29 | 只看该作者
好文章,必须收藏啊

回复 支持 反对

使用道具 举报

6蛮牛粉丝
1005/1500
排名
3177
昨日变化
14

5

主题

294

帖子

1005

积分

Rank: 6Rank: 6Rank: 6

UID
54335
好友
1
蛮牛币
1562
威望
0
注册时间
2014-11-9
在线时间
278 小时
最后登录
2018-8-24
12#
发表于 2018-8-14 14:03:08 | 只看该作者
讲解的很仔细,全面

回复 支持 反对

使用道具 举报

2初来乍到
146/150
排名
16341
昨日变化
10

0

主题

63

帖子

146

积分

Rank: 2Rank: 2

UID
36729
好友
0
蛮牛币
12
威望
0
注册时间
2014-7-28
在线时间
45 小时
最后登录
2018-8-14
13#
发表于 2018-8-14 14:17:43 | 只看该作者
感谢感谢感谢感谢

回复 支持 反对

使用道具 举报

7日久生情
1529/5000
排名
1007
昨日变化
5

0

主题

209

帖子

1529

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
37063
好友
1
蛮牛币
4422
威望
0
注册时间
2014-7-30
在线时间
311 小时
最后登录
2018-8-21
14#
发表于 2018-8-14 14:28:05 | 只看该作者
虽然在其它论坛已经看过了,不过还是赞一个
[发帖际遇]: 爱学习的企鹅 发帖时在路边捡到 1 蛮牛币,偷偷放进了口袋. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

5熟悉之中
822/1000
排名
2989
昨日变化
6

0

主题

94

帖子

822

积分

Rank: 5Rank: 5

UID
32989
好友
1
蛮牛币
1893
威望
0
注册时间
2014-7-7
在线时间
276 小时
最后登录
2018-8-25
15#
发表于 2018-8-14 14:38:55 | 只看该作者
顶顶顶,大神牛逼
[发帖际遇]: 一个袋子砸在了 mnpqxz 头上,mnpqxz 赚了 1 蛮牛币. 幸运榜 / 衰神榜

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

快速回复 返回顶部 返回列表