![腾讯游戏开发精粹](https://wfqqreader-1252317822.image.myqcloud.com/cover/110/26262110/b_26262110.jpg)
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人
1.8 动态障碍物
以上介绍均建立在预生成SDF的基础上,但在MOBA游戏中英雄技能带有阻挡效果是非常常见的,会在运行时生成动态障碍物。前面提到生成整张地图SDF的计算量大,因此根据动态障碍物重新生成整张地图的SDF不现实。要解决动态障碍物的情况,我们先来看一下SDF的CSG运算规则。
![](https://epubservercos.yuewen.com/EFD27D/14693592205506206/epubprivate/OEBPS/Images/figure_0029_0002.jpg?sign=1738964483-xiRh1Edp5i9WtdgT0gbldvo6OfyITnUA-0-c76282bc7b1ba5a81cbe58c10b47e806)
那么对于动态障碍物的情况,可以使用预生成的静态地图SDF和动态障碍SDF的叠加,即取二者的交集。同时动态障碍SDF可以直接用程序表示[2],比如常用的如图1.13所示的圆盘SDF和图1.14所示的矩形SDF。
![](https://epubservercos.yuewen.com/EFD27D/14693592205506206/epubprivate/OEBPS/Images/figure_0030_0001.jpg?sign=1738964483-Z8HJRma89uTskDxUP1ach5xzpmsweI1o-0-4756ea5f0ef5d5c6903e408afe9fa3f2)
图1.13 圆盘SDF
![](https://epubservercos.yuewen.com/EFD27D/14693592205506206/epubprivate/OEBPS/Images/figure_0030_0002.jpg?sign=1738964483-wTPepK1LdiWu4ezI3Bmbyk1835aHz84i-0-b3aa4386332835e75a6534b199f0039a)
图1.14 矩形SDF
圆盘SDF:
![](https://epubservercos.yuewen.com/EFD27D/14693592205506206/epubprivate/OEBPS/Images/figure_0029_0003.jpg?sign=1738964483-KdQCQlSQyINu7Krwmu8TI6qTrwiDSChK-0-86f4d6af6660c6af33b6a4b64334394d)
以下为计算圆盘SDF的代码。
// x为任意点坐标,c为圆盘中心,r为圆盘半径 float sdCircle(Vector2 x, Vector2 c, float r) { return (x - c).Length() - r; }
矩形SDF:
![](https://epubservercos.yuewen.com/EFD27D/14693592205506206/epubprivate/OEBPS/Images/figure_0030_0003.jpg?sign=1738964483-xyMJLsTzbxkpBbIx9JuJiBOXjgj7InJ4-0-5257d8e66dc4fdef03a626f448e20e1f)
以下为计算矩形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所示。
![](https://epubservercos.yuewen.com/EFD27D/14693592205506206/epubprivate/OEBPS/Images/figure_0030_0004.jpg?sign=1738964483-itSHAvdgZ4hQrLdGOPxon9V2Sml9WwNN-0-c19f9bb4d691b025025726e8b64b65c5)
图1.15 环形SDF可视为外盘对内盘的补集
对于部分英雄技能的打洞等跨越障碍物的功能,通过补集运算即可实现,非常容易。
至此,通过SDF的运算规则很好地解决了动态障碍物的问题,但程序SDF的计算量要比静态SDF查表插值的计算量大,因此不适合具有大量动态障碍物的情况。如果大量动态障碍物分布稀疏,则可以通过空间分割管理动态障碍物,从而减少程序SDF的计算次数。