在“矮人要塞”中,您一次可以在游戏中拥有成百上千的矮人,动物,妖精等,每种都有各自复杂的AI和寻路例程。我的问题是,这怎么不会导致明显的放缓?每个矮人都在自己的线程中运行吗?
在“矮人要塞”中,您一次可以在游戏中拥有成百上千的矮人,动物,妖精等,每种都有各自复杂的AI和寻路例程。我的问题是,这怎么不会导致明显的放缓?每个矮人都在自己的线程中运行吗?
Answers:
任何一个拥有如此多字符的线程的系统都会很快耗尽资源。线程可以使您访问额外的处理器内核,但它们并不能使任何事情本质上都更加高效,并且它们会带来开销。
简单的答案只是要有效处理游戏中的每个实体。
“矮人要塞”不是开放源代码,尽管有很多推测和逆向工程可以说明其全部工作原理,但我将重点介绍一些基本技术,以优化3D渲染的3D(而非3D图形,3D世界)。相同的类型。
与所有电子游戏一样,大量的烟雾和镜子从简单的规则和系统中营造出复杂的错觉。这些范围从使用简单的随机数一直无目标地移动到预烘焙高级节点网格以进行寻路。
说到寻路,通常对于大空间来说这是一个很难解决的问题,例如DF映射可以(多达768x768x64 IIRC),但是可以通过以下方式简化和加快问题的解决:
我不会介绍寻路的基础知识。大多数无赖猫使用A *,但是还有其他方法可以为猫皮。Mmmmm猫皮革..
使DF部队流行并充满活力的主要因素之一是他们的个人目标清单。实际上,许多无赖类游戏都具有基本水平。本质上,每个单位都有一份愿望清单(对于您的小伙子来说,他们可能会承担您要完成的任务),并且他们会根据自己的个性(统计数据)从中选择。
有些任务有要求。制作皮裙要求多夫在某家拥有X件商品的商店中。因此,所有这些都将被检查并作为任务添加到其列表中。就那么简单。
由于大部分时间单位会在运输过程中,因此对单位运行情况的检查可能非常快,在任何给定的时刻只有少数单位会做出选择,因此总体而言,即使是数百个或数百个单位也不会降低速度数千个单位。记住,在DF中,从蜜蜂到穴居人再到树木的一切都是单位。
在进行一些其他研究时,很显然,DF通常在做寻路方面做得很糟糕。并不是将地图分解成块,而是将地图分解成已连接的段或区域(这肯定比没有结果要好),因此我的上述评估甚至比DF想象的还要少。:)这并不是说DF由于其他百万种原因而令人惊讶。
它表明游戏中重要的是游戏。没有图形,没有出色的程序设计,没有出色的写作,没有出色的音乐,甚至没有界面;没有什么比游戏本身重要的多1%了。
从此页面:
从我的角度来看,[寻路]看起来很棒,因为有成千上万的字符同时完成。
TA:矮人本身大多以A *来回走动,并使用常规的旧街道距离试探法。棘手的部分是,如果他们不知道自己可以提前到达那里,就无法真正调用A *,否则最终将淹没地图并杀死处理器。
我不知道这是否绝对是他如何防止“淹没地图”,但是在游戏中这样做的通常方法是使用对A *的更改,称为“ 层次路径查找A * ”或HPA *。这个想法是将网格分成更少但更大的块,然后使用A *查找从每个块到其相邻块的最佳路径。您可以使用它来构建一个更小的图形,在该图形上为每个单元运行A *。
您还可以将这些块分组为更大的块,这就是“分层”的来源。
该算法只能找到接近最佳的路径,但是对于矮人要塞这样的游戏来说通常是可以的。如果存在,仍然可以保证找到路径。当没有路径时,它只会淹没较小的图形,从而节省大量时间。
HPA *还有一个抽象概念,即可以穿越某些地形但不能越过其他地形的单位(例如悬崖,空中单位可以越过而地面单位则不能越过)。这就是所谓的HAA *,并且有一个很接近的文章,解释它在这里。
您可以在此处阅读有关各种寻路算法的更多信息。
如果有的话,它是相反的-整个事情都在一个线程上运行,现在达到了成为阻塞因素的地步(我上次检查!)
快速的原因是没有精美的图形。这具有欺骗性,但最主要的是减慢绘图速度(在AAA标题中,请考虑超过三分之二的帧)。由于矮人堡垒是非常基本的,所以它将剩下的时间用于做有趣的事情。
我不知道DF是如何编码的,但是人工智能的数量并没有给我真正的印象,因为人们经常监督人工智能不需要精度。每隔几秒钟执行大多数工作是完全可行的。使用不精确的计算也是可行的。不完美会节省很多性能。您可以每100毫秒运行100个单位的决策例程,或者每秒运行1000个单位的决策例程,这将花费相同的CPU时间,但是...您有10倍的单位。
这是一个简单的示例,说明如何处理很多单位:
int curUnit;
Array<Unit> units;
[...]
while([...]) // Game Loop
{
[...game logic...]
// process 10 AIs per Frame
for(int i=0; i++; i<10)
{
curUnit++
if(curUnit == units.length()) curUnit=0;
if(curUnit < units.length())
units[curUnit].processAI();
}
// Update the position of all units, this should be as optimized as possible
foreach(Unit& unit in units){ unit.move(); };
[...graphics...]
}
越多,AI的响应就会越来越少,但玩家可能只会在极端情况下才会注意到它。