我已经在javascript中编写了一个组件实体系统一段时间了,但我一直在回到root问题。
如何处理特定实体 - 也就是单个实例或单一类型 - 功能?
以下是目前的情况:
我构建事物的方式,当一个项目实体被另一个实体存储在库存中时,它不会被销毁,只是剥夺了它的大部分组件。这样,如果它被删除,或者可能被检索以供使用,它可以用其旧状态重新激活。被剥离的组件存储在附加到实体的InstanceDataComponent中(这只是一个JSON对象)。
有一个小型系统可以管理物品是否可以被拾取并添加一个库存记录,其中包含存储物品的散列,数量和ID,但有些东西需要管理该实体的转换。 “item”状态为其“存储”状态。 应该做什么?在我看来,要删除的组件和要更改的数据的详细信息对于每个项目都必须是唯一的。
假设将来我希望实体在动态中切换两种行为。例如,来回踱步直到它被打扰,然后寻找玩家。什么会处理这种转变?
我觉得我对这里的问题和典型架构有一个根本的误解。处理这个问题的干净方法是什么?我是否应该为每组行为转换添加一个组件?难道最终会有太多的组件被美化的回调包装器?或者我错过了一个实体在存储在库存中时应该如何更改的内容?
对于可能正在经历这种情况的其他人的一些想法。
我目前的解决方案(经过几次迭代)是触发全局事件,例如itemPickupSystem:storedItem
和实体可以为其工厂方法中的任何事件附加处理程序。出于多种原因,这不具有可扩展性。我一直在考虑将这些事件移到队列中以便稍后执行。
我的工厂方法变成了回调定义的大杂烩,事情正在降级为回调地狱。此外,这个事件系统必须走,它是整个系统中唯一打破游戏循环串行性质的部分。到目前为止,每个系统都按照定义的顺序触发,所有逻辑都驻留在这些系统中。现在我无法保证实体将处于特定状态,因为这些回调可能在不同的点被触发。最后,因为执行被全权转移到不属于核心功能的代码,所以无法知道当事件被触发时调用堆栈会有多大。
答案 0 :(得分:0)
有时在实用网络复制方面最容易想到这个问题,组件之间的界限自然而然。
让我们说你的演员可以挥舞和储存一把剑。
我不会期望从inventorySword到presentationSword的'转换',而是在'inventoryItem'和'swordPresentation'之间有一个自然的描述。
在服务器上,将为每个玩家分配其库存中的项目列表。每个项目都有一个世界唯一的ID。清单项可能派生为'SwordItem',并具有SwordType和Condition%
的属性在客户端上,'swordPresentation'组件可能会处理要显示的网格的作业,通过第一人称相机显示时附加动画数据的套接字,以及如何平滑动画过渡。但这一切对于实际的游戏状态都不重要,它只是我们的客户看到这个世界的方式。
潜在地,如果您将游戏状态分发给每个客户,那么您通过网络传递的所有内容都将是当前玩家的库存,而对于其他玩家,每个玩家当前装备的项目以及它们的位置(假设他们在视力中
因此,考虑创建一个基于库存项目创建“swordPresentation”的工厂,找到可以作为参数传递的最小值,以创建组件的表示(可能是剑型,剑%条件等) )。
无论最低限度是您想要作为库存项目序列化的内容。
在复制数据之间建立清晰的界限意味着在编写多人游戏时性能更高,漏洞更少。当您编写单人游戏时,它会帮助您了解保存文件中的内容。