在实体系统中存储组件

时间:2012-07-21 20:08:13

标签: javascript arrays object dictionary entity

注意:这个介绍是关于实体系统的。但是,即使你不知道它们是什么,或者自己没有实现它们,它也是非常基本的,如果你有一般的Javascript经验,你可能有足够的资格来回答。

我在T =机器博客上阅读有关实体系统的articles

作者Adam认为实体应该只是一个id,可用于获取它的组件(即实体应该代表的实际数据)。

我选择了所有实体应存储在“一个地方”的模型,我实现此存储的主要嫌疑人是许多人使用的阵列阵列方法,这意味着动态实体ID代表属于实体的组件的索引,而组件按类型分组在“一个地方”(从现在开始我称之为“存储”),我计划以Scene的形式实施。 Scene将是一个处理实体组成,存储的对象,并且可以对实体(.addComponent(entityID, component)等)执行一些基本操作。

我不关心Scene对象,我很确定这是一个很好的设计,但我不确定是存储的实现。

我有两个选择:

A)使用数组数组方法,其中存储如下所示:

//storage[i][j] - i denotes component type, while j denotes the entity, this returns a component instance
//j this is the entity id

[
    [ComponentPosition, ComponentPosition, ComponentPosition],
    [ComponentVelocity, undefined, ComponentVelocity],
    [ComponentCamera, undefined, undefined]
]

//It's obvious that the entity `1` doesn't have the velocity and camera components, for example.

B)将存储对象实现为字典(技术上是Javascript中的对象)

{
    "componentType": 
    {
        "entityId": ComponentInstance
    }
}

字典方法意味着实体id是静态,这对于在实体系统本身之外实现游戏循环和其他功能似乎是一件非常好的事情。此外,这意味着系统可以轻松存储他们感兴趣的实体ID数组。显然,entityId变量也是一个字符串,而不是整数索引。

我反对数组数组方法的原因是删除实体会在删除单个实体时更改其他实体ID。

实际的实施细节可能会持谨慎态度,但我想知道哪种方法会更好地表现?

我也感兴趣的事情(请尽可能跨平台,但如果需要,请使用V8作为示例):

  • 访问属性时的开销有多大,以及如何在蹄下实现?让我们说它们是从本地范围内访问的。
  • 记忆中的undefined是多少,需要多少钱?我问这个,因为在数组数组方法中,所有内部数组必须具有相同的长度,并且如果实体没有某个组件,则该字段设置为undefined

1 个答案:

答案 0 :(得分:-1)

不要担心数组。它是JavaScript中的一个Object,即没有“真正的”数组,它只是索引是对象属性(字典,散列,映射)的数字“名称”。

这个想法很简单,一个Array有一个length属性,允许循环知道在哪里停止迭代。通过简单地从Array中删除一个元素(记住,它是一个Object),length属性实际上并没有改变。所以......

// create an array object
var array = ['one','two', 'three'];
console.log(array.length); // 3
// these don't actually change the length
delete array['two']; // 'remove' the property with key 'two'
console.log(array.length); // 3
array['two'] = undefined; // put undefined as the value to the property with key 'two'
console.log(array.length); // 3
array.splice(1,1); // remove the second element, and reorder
console.log(array.length); // 2
console.log(array); // ['one','three']
  1. 你必须意识到JavaScript并不像你期望的那样“工作”。性能明智的对象和数组是相同的,即像字典一样访问数组;
  2. 范围与其他“c风格”语言不同。 只有全局和函数作用域,即没有块作用域(永远不会为(var i)写入另一个作为(var i));
  3. 内存中未定义的内容与null完全相同。不同之处在于null是故意遗漏的值,而undefined只是偶然的(非故意的)缺失;
  4. 不要通过执行if(array['two'])检查字段是否存在,因为字段实际上可以保存 undefined,null,0,“”,false 的虚假值并评估为false 。请务必查看if('two' in array);
  5. 使用for(key in array)循环时总是使用if(array.hasOwnProperty(key)),因此您不会迭代原型的属性(以某种方式说明父级)。此外,构造函数创建的对象也可以使用'constructor'键循环。