I want to code my object (water with splashes) so when an object is floating inside it, the script checks the number of newly added objects and stops adding the object (or caps it). How can I make it so scene.addObject() does not add infinite objects, but rather add only like a set number, so lets say, an object striking water will do only one object rather than two.
Add the splash using a pool of meshes
When you use the last one, swap back to the firat using a index
have a global integer variable that you increment with each object added. Only add objects if that variable is less than your maximum allowed variable.
If you want to replace earlier objects when you reach the max, store the objects in a list. Use a global integer variable as a pointer to the list index, when you hit the max, set the index to 0. Have another boolean variable like ‘overwrite = false’ and set it to true when you hit the maximum then you know to delete the objects from the array before adding a new one.
to check the new objects are within another object you will have to use the raycast method, unless you can get away with doing a bounding box check
oh unless you are using UPBGE then you could use SCA_CollisionSensor(SCA_ISensor)
for i in scene.objects:
if “my_object” in i and not i in list:
list.insert(0,i)
obj = scene.addObject(“somebody”, own, 0)
own[‘counter’]+=1
if own[‘counter’]>=10:
#over work add object # list global # counter property
You can just add a check for whenever you attempt to use KX_Scene.addObject():
import bge
MAX_SCENE_OBJECTS = 20
def main(self):
if (self.owner.scene.objects > MAX_SCENE_OBJECTS:
self.owner.scene.addObject("Cube", "Cube_Spawner")
else:
print("ERROR: The maximum limit of scene objects has been reached.")
Problem is, whenever I put in a [] as in to put a single object from a list to determine if I have more than one object (say, a latticed crate), it will say that an object with the name does not exist with quotation marks. I have faced this before when trying to retrieve objects from lists - it sometimes says the object but it is in quotation marks, which really makes me scratch my head.
KeyError: "list[key]: 'insert object name here' key not in list'
Yet the name is correct. I try to get an object directly from a list that I made. Why is Python trying to get an object that is in quotes from the list. I am not requesting an object name, but an actual object.
There is a new logic node for upbge 0.3.6 that supports adding objects using a pool
@RPaladin, UPBGE python says that > is not supported between instances of EXP_ListValue and Int. Same with <, and >= and <=.
Also says that the self object has no scene (bge.logic.scene) attribute or objects attribute (part of bge.logic.getCurrentScene). You must use scene = bge.logic.getCurrentScene()
to get scene info and objects = scene.objects
to get the entire list of objects in the scene.
Since scene.objects is a list of all objects in the whole scene, you can’t just see if an object has a greater amount through a list because it is not a number. This is the real problem here, as I need to test how many objects that are in a list are being added to stop duplicates, or cap them out. This happens when the sensor is triggered more than once, like a collision sensor. And it’s not all objects in the scene through the list, it’s just one to several of them. Is there any way this can even be accomplished? I am stumped!
@BluePrintRandom I don’t use logic nodes, I use Python and Logic Bricks. I want to test objects from a list pool, and add them, but it says that the > or < symbols are not supported between lists and integers.
@technisculpt, the problem with global variables is that when I define them and add a value to them, when I try to use them.
I’m talking about this example:
import bge
global variable
variable = -1
if variable == -1:
variable = 0
if variable == 0:
variable = 1
Global variables stop working after using them in a lot of if, elif and else statements. How do I make them carry over like local variables?
i just ran that and it did work, variable was 1 at the end.
but anyway the global keyword is used within the block for which you want to access the global variable. So it would be more like:
variable = -1
if variable == -1:
global variable
variable = 0
if variable == 0:
global variable
variable = 1
but i don’t usually think of if statements as a block, although you’re indenting so they are, it’s more common to use it within a function:
variable = -1
def var_ops():
global variable
variable = 0
if variable == 0:
variable = 1
but if you don’t initialise a variable within a block is should retrieve it from the parent block without having to use the global keyword. I just meant use a global as in where it’s declared is not nested which puts it in the global namespace, typically at the top of the script
in more esoteric examples you can directly manipulate and pass the global or local scope as they are accessible in python as a dictionary;
variable = -1
globals()['variable'] = 1
print(variable) # variable is now 1
@technisculpt, how can I now make it so a piece of code checks the number of objects in a scene and then stops adding it if more than 1 instance is in the scene? How also can I check if the sensor is being triggered more than once using global variables? How can I go about this, since trying to check via lists and integers is impossible?
ok full disclosure this post was auto-suggested to me and I didn’t realise this was the game engine category, I don’t know anything about BGE/UPBGE or the sensor method (i just googled that), so there might be methods mroe suited to BGE/UPBGE. not really sure what you mean by instance. maybe post your code?
But could it maybe help to write a python class to wrap your blender object, and you store the class objects on a global list. Then you can iterate through the list and call the object methods.
i think you can get number of objects by something like len(bpy.data.objects) but maybe you should check out the pool of meshes mentioned above
Whoops, I forgot to add the .owner
to the end of the scene
words. Edited my post. You should be able to call KX_Scene directly from KX_GameObject now.
- init
import bge
cont = bge.logic.getCurrentController()
own = cont.owner
poolSize = 20
poolObject = "Splash"
if cont.sensors['StartUp'].positive:
pool = []
for x in range(poolSize):
added = own.scene.addObject(poolObject,own,0)
pool.append(added)
own['pool']=pool
own['Running']=[]
check a splash object out (any object can do this)
import bge
duration = 20
cont = bge.logic.getCurrentController()
own = cont.owner
pool_ob = own.scene.objects['PoolObjectName']
pool = pool_ob[pool]
if len(pool)>0:
next = pool.pop(0)
next.worldPosition = own.worldPosition
pool_ob['Running'].append( [ duration, next ] )
and finally we need a ‘runner’ to run the pool
def multi_delete(list_, args):
indexes = sorted(list(args), reverse=True)
for index in indexes:
del list_[index]
return list_
import bge
cont = bge.logicGetCurrentController()
own = cont.owner
i=0
for entry in own['Running']:
if entry[0]>0:
entry[0]-=1
else:
popList.append(i)
i+=1
multi_delete(own['Running'],popList)
Ok, I did actually achieve what I wanted via globalDict, but I am having trouble resetting it back to zero to allow splashing again when there is no positive pulse being sent. There must be a way to detect negative pulses, not just positive ones.
@BluePrintRandom, this code does not seem to add any objects to the list. It makes the Running property an empty list that removes it from the object while the game is running, and no appending of any object is done. I am trying to use this code to add splashes when a collision sensor is triggered. Also, how do I use the code? Do I put it in modules (aside from the one that runs the pool)? Or do I use it like it is? How would one use it?
I forgot .pop(0)
edited*
we run the init on frame 0 in ‘tap’ mode with a always sensor
we have another ‘delay’ 1 frame with 0 duration (forever) that runs the ‘run’ part of the code.
object that splash run the code to get a splash and ‘check it out’ like from a library
they add it to a active list, and they get put back to get used again.
we can do stuff like change object color etc.
we can do something similar to this but more performant using geometry nodes to aim them too / C++
bullet_Pool_3x_revision_5.blend (1.0 MB)
your ‘splash pool’ is similar to my bullet pool and casing pool problem
I just gave up and coded my splash sensor to have the sensors tap turned on (trigger only instantly set to true) and coded the splash sensor to turn off the True positive pulse. So I solved the conundrum myself.