Help to Pool Object in UPBGE

I’ve been publishing some games on UPBGE, but due to feedback from people who have tested my games, people have said that lags occur during the .exe, I believe it’s the simple system I’ve been using to add enemies (scene.addObejct). I found out that the pool exists, but I’m having difficulties implementing it in my code, could anyone give an example?

“”"
Offer a significant performance boost; it is most effective in
situations where the cost of initializing a class instance is high, the
rate of instantiation of a class is high, and the number of
instantiations in use at any one time is low.
“”"

class ReusablePool:
“”"
Manage Reusable objects for use by Client objects.
“”"

def __init__(self, size):
    self._reusables = [Reusable() for _ in range(size)]

def acquire(self):
    return self._reusables.pop()

def release(self, reusable):
    self._reusables.append(reusable)

class Reusable:
“”"
Collaborate with other objects for a limited amount of time, then
they are no longer needed for that collaboration.
“”"

pass

def main():
reusable_pool = ReusablePool(10)
reusable = reusable_pool.acquire()
reusable_pool.release(reusable)

if name == “main”:
main()

Look in this example downloaded for internet, how implement in UPBGE this system pool for instance objects and run?

if 'pool' not in own:
   own['pool']=[]
   for x in range(15):
       own['pool'].append(own.scene.addObject('PoolObjectName',own,0)

this creates the pool

to use it

if len(own.scene.objects['PoolObjectName']['pool'])>0:
    pool_item = own.scene.objects['PoolObjectName']['pool'].pop(0)
else:
   pool_item = own.scene.addObject('PoolObjectName',own,0)
   

and to return it to the pool after its aged out / or collided whatever

own.scene.objects['PoolObjectName']['pool'].append(pool_item)
2 Likes

bullet_Pool_3x_revision_5.blend (1.0 MB)

How does this script work? And how to access and remove item after done?

I use a kdtree to stream,

I spawn objects when a tile is filled, and to unload them when a tile is free

During the fill step we simply get the items from pools instead of adding them, and store them in a list in a dictionary using the tile index as the key

We use this when unloading the tile to repool the objects.

Thanks for your response. I was attempting to try it both the script above and the . blend you posted but I’m not quite sure how either works. I don’t know how to spawn item out of the pool. all I can do is append and pop them. Can you help me please.

Are you talking about the kd_tree bubble example?

yeah - with this system we can load in everything that falls on a tile when the tile is loaded,

we can even pack properties into each object (ammo etc)

look at the part that adds / removes tiles, this is where you will want to add / remove pooled items.

Thank you i will try and look at it again.

Yees! I have finally got it thanks you so much for your help😃!

1 Like

Is there a way to check if the object is the same one as the one that is in that world location then pop the corresponding object?

I really don’t understand the system. In a previous version the bullets were set invisible after use.
Making lots of things invisible could also make little fps drops as I understand. So I suppose that’s why here another systemis used.
Where does now the bullets go after use?
It looks like they or their data gets stored in vertices !?
I really would like to see a cleaned demo file. It’s already hard to understand uncommented code.
I see the “Bullet Pool” uses Gemoetry nodes but “Bullet Pool data” also has modifiers which can be deleted without disadvantage.
Ah, I give up, that’s over my head.

I’m using the script that doesn’t use geometry nodes mixed with the kx_bubble_tree example to make objects disappear out of range and not need to use the addObject as much.
`
#part if the script

import bge,ast
from bge import logic as R
import bpy
from mathutils import kdtree, Vector

cont = bge.logic.getCurrentController()
own = cont.owner
objects = R.getCurrentScene().objects
scene = R.getCurrentScene()
keyboard = bge.logic.keyboard

def main():

if 'init3' not in own:
    for obj in objects:
        name = obj.name.split(".")
        if name[0] != 'Empty':
            playing = str([(name[0],(obj.worldPosition[0],obj.worldPosition[1],obj.worldPosition[2]))])
            obj['Contains_Data'] = playing[:]
        



    own['init3'] = True


own['count'] = len([i for i in scene.objects if 'Contains_Data'])
#MOVMENT

  
#
if 'Grid' not in own:

    grid = []
    data = []
    for ob in own.scene.objects:
        if 'Contains_Data' in ob:
            if 'EMP' in ob:
                grid.append(ob.worldPosition)
                data.append(ob['Contains_Data'])
                ob.endObject()
    own['Data']=data 
              
    Tree =kdtree.KDTree((len(grid)))
    i=0
    for point in grid:
        Tree.insert(point ,i)
        i+=1
    Tree.balance()
    own['Grid']=grid
    own['Tree']=Tree

    own['Filled']={}
else:
    R = 90 
    near = own['Tree'].find_range(own.worldPosition, R)
    for point in near:
        if point[2]<R*.89:

            if point[1] not in own['Filled']:
                own['Filled'][point[1]]=[]
                
                data = own['Data'][point[1]]
                data = ast.literal_eval(data)
                
                for obj in data:
                    if len(own.scene.objects['PoolObjectName']['pool'])>0:
                         
                        added = own.scene.objects['PoolObjectName']['pool'].pop(0)
                    else:
                        added = own.scene.addObject(obj[0],own.scene.objects['Empty'],0)
                    
                    added.worldPosition =  Vector(obj[1] )

                    own['Filled'][point[1]].append(added)

                      
        elif point[2]>R*.90:

            if point[1] in own['Filled']:
                for obj in own['Filled'][point[1]]:
                    if not obj.invalid:
                        own.scene.objects['PoolObjectName']['pool'].append(obj)
                        #instead of deleting the object it is sent to an object called pools coridnates
                        obj.position[0] = own.scene.objects['PoolObjectName'].position[0]
                        obj.position[1] = own.scene.objects['PoolObjectName'].position[1]
                        obj.position[2] = own.scene.objects['PoolObjectName'].position[2]

                        
                del own['Filled'][point[1]] 

main()`

The code @BluePrintRandom place above goes into an object call “PoolObjectName” the 2D game example I placed in the https://blenderartists.org/t/game-programming-beginner/1420526/5 post uses that code feel free to take it apart to learn how it works.

1 Like

Thank you!!
I see in your code how unused objects just get positioned at a “Home”. This is how I also managed it in my simple pools. Easy to understand.
Things like kdtree are new to me, will only learn when needed. :wink:
Thank you!

1 Like

You are welcome. most of the code is from @BluePrintRandom I just mixed and edited it to work in my project. The kdtree is not part of the original pool script just used in the part to manage what object coordinates are closest and spawn them then send them back to the pool when out of range.