上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人
1.7 其他需求
1.7.1 如何将角色从障碍区域中移出
在MOBA游戏中有大量的击飞、击退等技能,角色被击中难免会“卡”在障碍区域中,对于这种情况,需要能够快速地将角色移动到最近的合适位置。因为梯度表示最大的变化方向,所以可以用梯度快速查找合适位置:
如图1.11所示,n为梯度方向,r=0.5为角色半径,实线圈位于障碍物内,圆心φ=-0.1;虚线圈位于合适位置,圆心φ=0.6,0.6= r − (−0.1)。
图1.11 查找合适位置示意图
当障碍是凸区域时一次迭代就能找到合适位置,是非凸区域时一次迭代可能无法找到合适位置,而MOBA游戏地图大多是非凸区域,因此需要多次迭代,直到φ(x′)≥r时停止。以下为迭代计算合适位置的代码。
Vector2 newPos = pos; for (int i = 0; i < 3; i++) { float SD = Sample(newPos); if (SD >= playerRadius) break; newPos += Gradient(newPos) * (playerRadius - SD); }
1.7.2 角色不能越过障碍物的远距离移动
当角色进行瞬时远距离移动,比如闪现,但又要求不能越过障碍物(能越过障碍物的情况则使用上面的方法)时,就需要进行连续碰撞检测来规避穿越障碍物的情况。建设使用圆盘投射(Disk Casting)进行规避,基于SDF的圆盘投射的优势在于迭代步进可以使用当前位置的φ值,如图1.12所示,这大大减少了迭代次数。
以下为圆盘投射计算位置的代码。
// oriPos:原始位置,dir:冲刺方向,radius:角色半径,maxDist:最大冲刺距离 public Vector2 DiskCast(Vector2 origin, Vector2 dir, float radius, float maxDist) { float t = 0f; while (true) { Vector2 p = origin + dir * t; float sd = Sample(p); if (sd <= radius) return p; t += sd - radius; if (t >= maxDist) return origin + dir * maxDist; } }