Javascript 在实体系统中存储组件
注:本介绍是关于实体系统的。但是,即使您不知道这些是什么,或者您自己还没有实现它们,这是非常基本的,如果您有一般的Javascript经验,您可能会有足够的资格来回答 我正在T=machine博客上阅读有关实体系统的文章 作者Adam建议,实体应该只是一个id,可以用来获取它的组件(即实体应该表示的实际数据) 我选择了所有实体都应存储在“一个地方”的模型,而实现这种存储的主要原因是许多人使用的数组方法,这意味着表示属于实体的组件索引的动态实体id,而组件在该模型中按类型分组“一个地方”(从现在起,我将称之为“存储”),我计划将其实现为Javascript 在实体系统中存储组件,javascript,arrays,object,dictionary,entity,Javascript,Arrays,Object,Dictionary,Entity,注:本介绍是关于实体系统的。但是,即使您不知道这些是什么,或者您自己还没有实现它们,这是非常基本的,如果您有一般的Javascript经验,您可能会有足够的资格来回答 我正在T=machine博客上阅读有关实体系统的文章 作者Adam建议,实体应该只是一个id,可以用来获取它的组件(即实体应该表示的实际数据) 我选择了所有实体都应存储在“一个地方”的模型,而实现这种存储的主要原因是许多人使用的数组方法,这意味着表示属于实体的组件索引的动态实体id,而组件在该模型中按类型分组“一个地方”(从现在起
场景
。场景
将是一个处理实体合成、存储的对象,并且可以对实体执行一些基本操作(.addComponent(entityID,component)
等等)
我不关心场景
对象,我很确定这是一个很好的设计,但我不确定的是存储的实现
我有两个选择:
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中的对象)
字典方法意味着实体id是静态的,这对于在实体系统之外实现游戏循环和其他功能来说似乎是一件非常好的事情。此外,这意味着系统可以轻松地存储他们感兴趣的实体id数组。entityId变量也可以是str很明显,ing与整数索引相反
我反对数组方法的原因是删除实体会使其他实体ID在删除单个实体时发生变化
实际的实现细节可能会让人担心,但我想知道哪种方法在性能方面会更好
我也感兴趣的东西(请尽可能跨平台,但如果需要,请以V8为例):
- 访问属性时的开销有多大,如何在hoof下实现?假设它们是从本地范围内访问的
- 内存中的
是什么,需要多少?我问这个问题,因为在数组数组方法中,所有内部数组必须具有相同的长度,如果实体没有特定的组件,则该字段设置为未定义
未定义
- 不用担心数组。它是JavaScript中的一个对象,即没有“真实”数组,只是索引是对象属性(字典、哈希、映射)的数字“名称”
想法很简单,数组有一个length属性,允许循环知道在哪里停止迭代。只需从数组中删除一个元素(记住,它是一个对象),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']
if(数组['two'])
来检查字段是否存在,因为字段实际上可以包含未定义、null、0、“”、false的falsy值并计算为false。请始终使用if('two'在数组中)
for(key in array)
循环时,请始终使用if(array.hasOwnProperty(key))
,这样就不会迭代原型的属性(从某种意义上说是父属性)。此外,构造函数创建的对象也可能使用“constructor”键循环啊哈,所以,基本上,这意味着我可以有一个包含999999999999个元素的数组,前99999999999个元素是未定义的
,最后一个是1
,它占用的内存量与[1]
?完全相同。虽然,因为你没有更快执行的好处(您处理的是字典,而不是数组)您也可以使用对象并为属性输入有意义的名称。如果您有更多歧义,请将它们添加到问题中,否则,请接受我的回答:)这个答案似乎有很多误解。例如,没有“键为'2'的属性”“在变量数组中;有一个值为“2”的元素。此外,大多数现代JavaScript引擎声明性能相同是不正确的;虽然访问数组和对象的语法相似,但其内部实现却大不相同。对于某些操作,阵列速度将快几个数量级;查看您的错误概念:>>例如,变量数组中没有“键为'two'的属性”;有一个值为“2”的元素。
// 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']