打算用rust写项目, 最大的问题就是链表, 彼此引用问题.
比如房间型游戏服务器, 每个房间都是局独立游戏. 每个游戏game有自己的节点, 怪物, 碰撞组件, 各种模块.... 这些部件为了方便使用和模块化都会引用*game, 而game中又会以数组方式存储这些部件的指针.
游戏即是这样, 想要模块化, 想要高度设计, 想要逻辑清晰, 互相引用指针是必须大量存在的. 除非: 存储部件id, 每次通过id获取对应游戏的对应部件, 这浪费性能,不利于使用.
问: rust是否不适合实际项目? 虽然rust是新式语言, 但是综合成本是否比C++更大?
附加: 目前使用golang, 为了降低垃圾回收成本, 使用uintptr 或 arr[id]标识, 写的很不优雅; c++ module编译器都未实现, 代码没法写;
1
共 7 条评论, 1 页
评论区
写评论不管你用哪种方式写游戏,建议你先上手写了之后再来判断,很多问题都是在写的过程中浮现出来的。比如你最开始的例子,多房间的游戏服务器。你可能觉得每个房间里的components都不多,但ECS是允许你一次性遍历完所有房间的同种类components的。在这种情况下,get component带来的一次性overhead可以忽略不计。
ECS的核心思路是data oriented,它本来就是要以增大add component的开销为代价,来换取get component的遍历速度。它还有其他的一些优势:
ECS当然不是银弹。如果你没有大量components需要遍历的话,AoS (array of struct) 确实也是一种思路。但在这种情况下,你也并不需要太担心遍历的开销,你甚至可以用hashmap存储你的所有components.
但无论在哪种情况下,如果你真的想要一个低耦合的游戏,指针都不是你所必须的,最起码borrow不是。你可以看看其他的指针类型,比如unsafe的ptr,比如weak、Rc,比如自己实现一个integer handle来模拟指针(并不会有什么开销,汇编层面会被优化掉的)。
--
👇
sstudioer: thanks;
不考虑 cache miss: ecs查找组件, 需要寻找的过程, get_componnet() 是个递归判断. 考虑 cache miss: ecs只有在频繁递归component的情况下才有优势.
C#: 这类垃圾回收语言用 ECS, 本身降低垃圾回收的效果就是显著的, 所以unity必须使用ECS; C++ RUST: 用ECS就很费解;
--
👇
Pikachu: 其实ECS的思路是这样的。
thanks;
不考虑 cache miss: ecs查找组件, 需要寻找的过程, get_componnet() 是个递归判断. 考虑 cache miss: ecs只有在频繁递归component的情况下才有优势.
C#: 这类垃圾回收语言用 ECS, 本身降低垃圾回收的效果就是显著的, 所以unity必须使用ECS; C++ RUST: 用ECS就很费解;
--
👇
Pikachu: 其实ECS的思路是这样的。
其实ECS的思路是这样的。
每种component都是单独的数组。具体细节你可能得读代码了,涉及到稀疏数组、archetype等一些用于优化搜索速度的设计。
补充一个关于ECS中archetype的blog: https://ajmmertens.medium.com/building-an-ecs-2-archetypes-and-vectorization-fe21690805f9
--
👇
sstudioer
对于esc不能理解的是: 比如要使用entity的 physics组件, 则需要
--
👇
Pikachu
再补充一个链接: are we game yet?
这个网站汇总了rust中游戏相关的生态系统、已经实现的游戏和参考资料。如果你需要做游戏的话,应该是一个比较有用的参考网站。
如果仅限游戏相关的话,我觉得你可以了解一下ECS (entity-component-system)。我在这里先粗糙地描述一下,如果想要深入了解,可以看最后面的链接。
不妨先只考虑一个房间。你的方法是,各种组件在game这个全局变量中以指针数组形式存在,指针指向的内存位置则是分散且不确定的。 而ECS的思路,则是一张表。每一种组件在是表中独立的一列,如位置、速度等。每一个实体则是表中独立的一行。每一列组件可以粗糙地认为是以数组的形式存在,通过index进行查找。 如果不考虑CPU cache miss的情况,这两种方式的效率应该是相近的,都是两次寻址。而如果考虑cache miss的话,ECS的方式则有明显优势,因为同一种组件在内存中是连续的,所以你可以很快速地遍历同一种组件。
回到你的问题上来,
这段话基本上是错误的。互相引用指针并非必须存在,存储数组index也并不会浪费性能。
ECS并不是一个新鲜的概念,也确实已经被广泛用于各种游戏中(galgame除外)。我上面的描述并没有非常精确,只涉及了直觉上的理解,你应该能在知乎等地方找到很多更详细的文章介绍,我这里先贴几个链接以供查阅。 相关链接
如果部件是一个树状/层次结构,可以考虑向下用Rc,向上用Weak
我觉得rust的优势在于需要很显式地考虑一个部件的所属,到底一个东西由谁管理由谁清理。然后就是高性能并行计算的时候避免出现竞争。