1.8 動態障礙物
以上介紹均建立在預生成SDF的基礎上,但在MOBA游戲中英雄技能帶有阻擋效果是非常常見的,會在運行時生成動態障礙物。前面提到生成整張地圖SDF的計算量大,因此根據動態障礙物重新生成整張地圖的SDF不現實。要解決動態障礙物的情況,我們先來看一下SDF的CSG運算規則。

那么對于動態障礙物的情況,可以使用預生成的靜態地圖SDF和動態障礙SDF的疊加,即取二者的交集。同時動態障礙SDF可以直接用程序表示[2],比如常用的如圖1.13所示的圓盤SDF和圖1.14所示的矩形SDF。

圖1.13 圓盤SDF

圖1.14 矩形SDF
圓盤SDF:

以下為計算圓盤SDF的代碼。
// x為任意點坐標,c為圓盤中心,r為圓盤半徑 float sdCircle(Vector2 x, Vector2 c, float r) { return (x - c).Length() - r; }
矩形SDF:

以下為計算矩形SDF的代碼。
// x為任意點坐標,c為矩形中心,rot為矩形旋轉角度,b為矩形邊長 float sdBox(Vector2 x, Vector2 c, Vector2 rot, Vector2 b) { Vector2 p = Vector2.Dot(x - c, -rot); Vector2 d = Vector2.Abs(p) - b; return Mathf.Min(Mathf.Max(d.x, d.y), 0f) + Vector2.Max(d, Vector2.zero).Length(); }
盤為內部不可行走的動態阻擋,對于內部可以行走的環形阻擋則可視為外盤對內盤的補集,如圖1.15所示。

圖1.15 環形SDF可視為外盤對內盤的補集
對于部分英雄技能的打洞等跨越障礙物的功能,通過補集運算即可實現,非常容易。
至此,通過SDF的運算規則很好地解決了動態障礙物的問題,但程序SDF的計算量要比靜態SDF查表插值的計算量大,因此不適合具有大量動態障礙物的情況。如果大量動態障礙物分布稀疏,則可以通過空間分割管理動態障礙物,從而減少程序SDF的計算次數。