An INTJ blog; subscribe to me, you can know what you never knew
散弹枪思路——服务器客户端随机数同步
Post:2022-05-15 20:55:01
Tags:/
UE
/
Visit:
线性扫描枪的最简单实现的思路
- 一、从准星位置发出射线检测阻挡物,目的是获取当前阻挡物。
- 获取准星在3D世界的位置(Position,Direction)
- 将Position作为起点,方向为Direction,方向如果是单位向量记得乘以一个比较大的数。
- PS:我是觉得这个数可以根据枪支类型来改变,冲锋枪 / 手枪可以小一点,狙击枪远一些。
- GetWorld()->LineTraceSingleByChannel()(UE发出射线检测的函数)
- 如果碰到阻挡物,则拿阻挡物的位置返回;碰不到就直接拿最长距离。
- 二、将获取到的阻挡物的位置作为End向量。
- 获取枪口位置Location,使用他作为Start的向量。
- 当前获取的阻挡物 HitTarget - Start 为方向向量,可能有时候够不着,可以乘以一个1.X的系数。
- GetWorld()->LineTraceSingleByChannel()(UE发出射线检测的函数)
- 如果是本地游戏,检测到就应用伤害ApplyDamage即可;网络游戏要在服务器ApplyDamage(UE检测当前是否为服务器函数HasAuthority())。
- 应用特效(射击轨迹,终点特效,枪口特效)。
改进版本的线性扫描枪
- TODO: zhongqian 这里应该有一张图片解释一下原因。
- 原因:你从准星作为起点获取的阻挡物可能提前被挡住了。
- 修复BUG:
- 在一执行后,需要在以枪口为起点,阻挡物为终点,使用射线判断一下是否有其他阻挡物提前阻挡在枪口到原来的HitTarget中间了。
散弹枪实现版本
- 首先,需要知道的是散弹枪与之前实现的手枪之间的差别是什么?
- 单个子弹与多个子弹(散弹枪一般都是多颗子弹一起发射)
- 散弹:是范围伤害而不是单体伤害。
- 实现思路:
- 每颗子弹单独计算,说实话有点浪费了。
- 在一定范围内用一个圆包围着所有子弹,所有子弹均落点在圆内。
- PS1:因此这个圆的远近与大小决定了这个散弹枪的性能,如果远距离 + 小圆可以表现出独头弹的效果。
- PS2:圆的半径与距离应该存在一个正相关的关系。
- 具体流程,PS:这个流程插入在 最简单实现的思路 与 改进版本的线性扫描枪 之间:
- 获取当前Start到HitTarget的归一化向量
- 计算到随机圆中心的向量
- 在随机圆内随机生成的向量
- 计算 射击终点 & 发散圆内某一点的最终位置
- 计算 到起始点到随机点的向量
- 返回 从起点到终点的随机圆的向量 * 一个非常大的值 作为 HitTarget
- 如果服务器与客户端同时计算会导致随机数不一致的问题,交给客户端计算随机数;当然,如果预防作弊,则记录一下弹道,如果很长一段时间弹道计算在客户端计算有问题,则需要进行以下我的头脑风暴结果:
- 如果遇到完全集中在一个点并发生了很多次,则有作弊嫌疑;
- 如果散弹枪的每颗子弹都远距离(设置一个阈值)命中并发生了很多次,则有作弊嫌疑;
线性扫描枪支使用客户端预测算法
- 思路:
- 在客户端中如果击中角色先把特效全部使用,但是逻辑伤害交给服务器去计算,计算完毕后返回并应用被击中角色上。
- 效果 / 优点:先应用特效能够让高Ping的客户端玩家减轻卡顿的体验,但是关键的逻辑计算依然是交给服务器处理。
- 缺点:如果客户端因为高Ping而当前判断不够准确,只会有击中特效而服务器逻辑计算失败,会影响玩家体验。