- 騰訊游戲開發精粹
- 騰訊游戲編著
- 553字
- 2019-08-30 16:20:42
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; } }