![]() |
Attention | Topic was automatically imported from the old Question2Answer platform. |
![]() |
Asked By | danielmeridew |
Hello!
I am trying to create a bullet-hell type game similar to Vampire Survivors.
Due to the sheer number of entities, I am thinking about creating a pool_manager.gd singleton that pre-instances all my items, mobs and projectiles.
These entities all have movement/collision logic as you would expect.
I’m trying to determine if this is the best approach, and I have questions like:
- should I instance them as a child of the pool_manager and then move them when required?
- does this negate requirements for enabling/disabling collision/movement logic?
- should they be directly instanced into their game node instead?
- is this even the best approach?
I realise this question is fairly broad, I was hoping on some advice/guidance on a way to manage large number of entities efficiently as possible.
See work in progress pool_manager.gd code below if you are interested.
extends Node
const MOB_POOL_SIZE = 1000
const ITEM_POOL_SIZE = 500
const PROJECTILE_POOL_SIZE = 2000
const MobScene = preload("res://mobs/base_mob.tscn")
const ItemScene = preload("res://items/item.tscn")
var projectile_scenes = {
"gauss_round": preload("res://equipment/projectiles/gauss_round.tscn")
}
var projectile_pools = {
"gauss_round": []
}
var mob_pool = []
var item_pool = []
var projectile_pool = []
var mob_parent = null
var item_parent = null
var projectile_parent = null
func initialize_pools():
_init_pool(MobScene, MOB_POOL_SIZE, mob_pool, mob_parent)
_init_pool(ItemScene, ITEM_POOL_SIZE, item_pool, item_parent)
for projectile_type in projectile_scenes.keys():
_init_pool(projectile_scenes[projectile_type], PROJECTILE_POOL_SIZE, projectile_pools[projectile_type], projectile_parent)
func set_mob_parent(parent):
mob_parent = parent
func set_item_parent(parent):
item_parent = parent
func set_projectile_parent(parent):
projectile_parent = parent
func _init_pool(scene, pool_size, pool, category_parent):
for i in range(pool_size):
var obj = scene.instantiate()
obj.hide()
obj.set_meta("original_collision_layer", obj.get("original_collision_layer"))
if category_parent:
category_parent.add_child(obj)
pool.append(obj)
func acquire_mob():
return _acquire_object_from_pool(mob_pool)
func release_mob(mob):
_release_object_to_pool(mob, mob_pool, mob_parent)
func acquire_item():
return _acquire_object_from_pool(item_pool)
func release_item(item):
_release_object_to_pool(item, item_pool, item_parent)
func acquire_projectile(projectile_type):
if projectile_type in projectile_pools:
return _acquire_object_from_pool(projectile_pools[projectile_type])
return null
func release_projectile(projectile, projectile_type):
if projectile_type in projectile_pools:
_release_object_to_pool(projectile, projectile_pools[projectile_type], projectile_parent)
func _acquire_object_from_pool(pool):
for obj in pool:
if not obj.visible:
obj.show()
obj.collision_layer = obj.get("original_collision_layer")
obj.sleeping = false
return obj
return null
func _release_object_to_pool(obj, pool, category_parent):
if obj in pool:
obj.hide()
obj.sleeping = true
if category_parent and obj.get_parent() == category_parent:
category_parent.remove_child(obj)
add_child(obj)
obj.collision_layer = 1 << 19
Pool menager approach seems reasonable. The way I understand it, the only problem with large amount of entities is actually instantiating them. So You can menage their movement and collision however You please, but they all should be created beforehand and reused.
Inces | 2023-05-04 19:40