模拟游戏世界中大量实体的绝佳方法


33

假设您有一个游戏,其中有许多实体(许多)服务于某些功能,但并非总是需要或需要在每个框架中都考虑所有这些功能。我正在研究的具体问题是存在一个包括器官在内的人体的详细模拟。

在游戏中,每个生物都有自己的身体,身体分成较小的部分(躯干,腿等),有时这些部分包含器官,这些器官在体内发挥特定的功能。器官的当前用途或作用是未知的。毕竟,动物可能肚子空了,因此不需要消化任何东西。当您在世界上拥有许多生物时,检查或模拟每个帧中的每个对象将是非常荒谬的,而且成本很高。因此,我正在考虑一种巧妙地区分需要更新的对象和不需要更新的对象的方法。

我想出的似乎是至少可以的解决方案。它创建了一个简单的队列/堆栈(本质上是每个元素在读取后即被删除;顺序无关紧要),称为“注意堆栈”,其中需要模拟的对象驻留在该堆栈中。需要注意的对象将简单地放在堆栈上由其他对象放在那里。这些对象可能会实现带有Simulate()函数的简单接口。

应用于我之前的消化示例,这将意味着:

玩家从清单中选择要吃的东西(假设是面包),并将其放入角色的口中,然后将口放到注意堆栈中。在下一帧中,将嘴从堆栈中取出,并调用其Simulation()函数。由于是嘴巴,因此在这里模拟咀嚼是合理的。这可能会持续几帧,在此过程中,嘴巴会不断将自身放到烟囱上,直到它决定可以吞咽食物为止。在这种情况下,嘴巴将嚼过的面包放进胃中(我知道它不会直接进入胃中,但是为了简化起见,食管被省去了),然后也将其放到注意堆栈中。在下一帧中,开始消化过程的模拟。其余的必要器官等等。

可以预见的问题是空转对象。熟睡的动物就是一个很好的例子。可以通过将熟睡的动物放在堆栈上并每次检查是否需要唤醒来完成上述操作,但这似乎很浪费,因为这是唯一要做的事情。为了使闲置对象更有效率,我计划添加一种时间表,以存储要在特定时间执行的作业。如果动物入睡,它将按照该时间表进行工作,该时间表将在动物入睡后的一定时间内进行。然后,这项工作将负责将熟睡的动物再次放到注意堆栈中。现在,您可以说不在注意力集中的睡眠动物可能会因为没有模拟AI而错过被某物攻击的机会,

现在,老实说,由于缺乏经验,我不知道这是否可以完美解决该问题。我接近可用的东西了吗?通常这是如何完成的,或者有人有什么建议或更好的解决方案?

Answers:


10

这正是我们在Stendhal中解决此问题的方式。在我们的案例中,有很多事情是周期性发生的,但并非每轮都发生:愈合的咒语,植物进一步生长,尸体退化,地面上的物品即将过期。

我们的回合数每回合都会增加。并且,我们维护了将来转弯编号的映射,该映射指向在该转弯中需要通知的一组对象。


如果与此同时有其他东西与对象交互怎么办?例如,沉睡的动物可能会被一块敲打的石头唤醒。在这种情况下,您应该删除动物的时间表吗?
Emiliano

这取决于情况:如果完成的动作是无害的(例如在清醒时醒来),我们就让它发生。但是,如果操作用尽了一些资源,我们将搜索待处理的队列并将其删除。
亨德里克·布鲁默曼

14

听起来像是输入的问题:您的键盘上有100多个按键,但又不想检查每一帧上的每个按键,那么您该怎么办?

两个答案:轮询或系统消息。

轮询=在游戏中真正重要的任何时候,查询键盘按键(或您所用的物体)的状态。其余时间,请忽略它们。

消息=在按下或释放键时(需要注意),让每个键盘键(对象)将某些内容放入消息队列中。在游戏循环的每次迭代中,它都会浏览队列并在继续之前解析所有消息。


10

因此,我将从实现上退后一步,并从设计角度审查问题。您是否有一个可靠的计划来显示要包含在此模拟中的所有详细信息?

例如:

  • 玩家能否分辨出空腹动物和饱腹动物的区别?
  • 当他们在游戏中进行互动选择时,这些信息对他们是否有影响?
  • 观看动物的玩家能否始终如一地预测模拟事件的结果,还是随机数就足够了?

基本上,一般的经验法则是不要使模拟比其输出更复杂。一天结束时,如果您只有绵羊动画了,那就放牧,睡觉,逃跑吧。那么,决定选择哪种状态的决定因素实际上并不重要。所有玩家将看到的是绵羊,它们在夜间睡觉,逃避危险并在白天吃东西。

行为模拟是很多工作的乐趣,但始终牢记最终用户的体验。


是的,玩家将能够分辨出差异,并且这会对游戏玩法产生一些影响,但是目前更多的是一种“ mm头”的娱乐性。有点像《矮人要塞》中的伤口系统,它也很详细,但可以忽略不计。但是,正如您已经提到的,工作很有趣,这是我目前的重点。
马克·穆勒

9

几年前,我在一款游戏上遇到了类似的问题-对象的模拟非常复杂,无法对世界上的每个对象进行详细的模拟。

解决方案是将LOD概念用于仿真。播放器视图内的对象将运行完整模拟。远离播放器的对象会定期进行高度简化的模拟。当物体进入玩家的视野时,它们将从路线,定期模拟更新到详细,定期更新的过渡。


2

有计划的解决方案很好。请注意,每个实体都应有一个指向其将来动作的指针列表,这样可以在必要时使将来的动作无效。就是 受到攻击时,睡眠中的动物会立即唤醒,因此您将来必须取消其唤醒动作。


1

有一个设计模式。我认为它叫做数据库对象?

基本上,您保留一只可以代表游戏世界中所有非特殊绵羊的“模板”绵羊,以相同的方式绘制它们,将唯一数据保留在模板对象内,例如以绵羊位置和/或时间表-自剪切。然后,每当需要使绵羊成为唯一绵羊时,都可以创建一个特定实例来跟踪该绵羊。

动画也是如此。如果它是每个实例共有的空闲动画或事件,则可以驻留在模板实例中,在模板实例中可以单独安排更具体的动画。

很久以前,我为编程竞赛编写了一个游戏,其主循环在整个场景中仅调用animate()。它使用函数指针根据需要将其他闲置动画替换为其他动画,并使用该技术支持继承的动画(例如旋转站立在旋转光盘上的角色)。

这本质上类似于使用委托进行动画处理。


3
轻量级模式,是什么意思?
topright 2010年

0

状态机会工作吗?动物处于例如睡眠状态,进食状态,奔跑状态等。对于每种状态,您关联一个活动器官列表。因此,您访问每个动物的每个帧,打开状态,查找该状态的器官列表并在每个器官上执行更新。


我认为那会使事情复杂化,因为动物中必须有可能发生多件事。例如,仅仅因为胃在消化某些东西,并不意味着心脏停止跳动或动物停止行走。当然,您可以定义一组状态,每个状态都考虑到某些功能,但是状态的数量会异常庞大。
马克·穆勒

每个状态可能发生多种事情,因为您将所有活动器官存储在一个状态上,并且每帧执行一次。但是,模拟中发生的许多事情似乎都与状态转换相适应。例如咀嚼->消化。但是我想你是对的,一种动物不能只有一种状态。有肢体发生状态转换,这与消化系统中发生的状态转换无关。但是,也许比您拥有的更为复杂。只是认为这可能是要考虑的事情。
埃里克·恩海姆
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.