Removing all objects but the stage and its children?

I’m trying to make a shooter-map that can clear the game of all projectiles and players, leaving only itself. I don’t want to put a property on each stage-object absolving it from deletion, because that adds a tremendous level of tedium on more complex stages down the line. Something that may be important to note is that a master object (an Empty) is set as the root of a parenting-tree of whatever size the map needs.

Is there any streamlined method to go about this? Would just blanking everything and respawning the map in one go work on more complex levels? I’ll test this last idea right now, but I can only go so far without making an ACTUAL level, y’know? Any advice is appreciated. :slight_smile:

You can use this code.

It loop over the scene objects and check if their “ultimate” parent is your master object. If it is not, it delete the object. Replace “master object name” by the real name of your master object.

Messed up the code, wait a second.


I just discovered Object Groups, which LOOKS like it’d be a great tool (no need to climb trees), but… it looks as though I can’t actually access that data in-game! The official documentation says to use groupObject, but dir() says that it doesn’t exist. Is that information accessible through other means?

Sorry for the wait. Be sure to rename “Master” to your object master name.


from bge.logic import getCurrentScene

scene = getCurrentScene()

for obj in scene.objects:
    
    if obj.name != 'Master' or scene.active_camera():
        parent = obj.parent
        
        if parent == None:
            obj.endObject()

@Lorenzo - groupObject was added in a more recent build of Blender. To use it, grab a recent build from the Blender BuildBot or from Graphicall.

dberube’s method loops through all objects in the scene to delete those that are the top-level parents of other children that aren’t named “Master”, and aren’t the scene camera (though it will delete the game camera if you’re not looking through it).

Better yet…

Instead of finding every object named ‘Master’, you could use Properties!

For example:


scene = bge.logic.getCurrentScene()

def reset_stage(property):
    for ob in scene.objects:
        if not hasattr(ob, property):
            ob.endObject()

reset_stage("Stage_Object")

Using Properties could help make things a little cleaner (in my opinion). Of course, you may want to append more lines of code to properly remove unwanted objects. Like, if you wanted to remove only powerups from the stage, but not the players, you could do this:


scene = bge.logic.getCurrentScene()

def remove_objects(property):
    for ob in scene.objects:
        if hasattr(ob, property):
            ob.endObject()

remove_objects("powerup")

Now, you may remove specific groups of objects.
I hope this helps :slight_smile:

What? Only one object is named “Master.” Thanks for the heads-up, Lune! I thought I had the most recent build, but… I guess not~!

The problem with dberube’s method is that grandchildren etc. of Master will get deleted as well. I could use childrenRecursive, but comparing each object against a potentially giant list seems grossly inefficient.

Setting Properties is exactly what I’d like to avoid: I want this to be as automated as possible, and forcing map-makers down the line to setting a variable like that is clunky. Making a script to run through Master’s children to set it also strikes me as less than optimal.

Just accessing such a convenient specifier as Groups seems the best way to handle this problem, but I can’t figure how to use it; even in the lastest GraphicAll build (Blender 2.65.9 - Fastest Build: All CUDA Kernels + OSL). The member groupObject is there, but specifying a Group in the editor doesn’t affect it. Even if for its own sake, how do I use this feature???

The groupObject variable is a reference to the group object of a group instance that is placed in a scene.

For example, make something like a couch and cushions (which are separated), and place it in another scene. Add the objects to a group (named CouchGroup, for example), and then go to your game scene and add in the group instance. It will make a new object called CouchGroup that contains all of the other objects that are added to the group (which is the couch). This is good, since you can easily and quickly build a level up out of objects that all share properties (i.e. change the shape of one of the couches, and they all change).

At run-time, the BGE adds the game objects that are present in the group. In a more recent build, the groupObject variable was implemented, which allows you to refer to the group object that all objects in the group are ‘added by’. This is useful because you can set specific functions or logic dependent on groups of objects of similar type. For example, say you make it so that couches restore your stamina. With the groupObject variable, you could set a variable in specific couches that change how much stamina is restored without writing a whole other script and creating another group for those other couches. You can then access the property through the group object (object.groupObject).

A (possibly) simple solution to your problem would be to set up global lists (stored in the logic module, or the logic.globalDict dictionary) for your players and your projectiles. Each time a player or projectile is created and initialized, add it to the global list. If it’s deleted, then remove it from the list. When you want to clear the screen, just loop through the lists and end all of the objects you come across. This should be pretty efficient. Even if it isn’t, it probably won’t matter that much since you’re only going to do it once (i.e. clear the screen, and then move on to the next level).

dberube4’s method goes through all ROOT-objects.

Deleting them removes their children too.
As the “master” is the only one which is not deleted it will survive together with all of it’s children.

BTW: Why are you adding so much objects just to delete them? You can simply start a scene without. This saves memory and loading time.

for projectile is better use a life time

sce.addObject(“projectile”, own, 10)

automatically get destroyed after 10 frame
or if you want keep it more time , 60 frame = 1 second .(more or less)

the same can be used for other obj ,as piece brocken of destuction,
usually rigid body, that is better ever putting some time limit

PS: uhm, for group obj i fear that is not usable :spin:

but the code to use is this:
#from spawned obj
master = own.groupObject #it return one obj Id or None
members = master.groupMembers#return a list of obj

I’m trying to do a mass deletion because I’m making a multiplayer-based shooter, with match-resets instead of new levels. Think Quake and TF2. :slight_smile:

UPDATE:
Looking over all the objects that would be deleted, and comparing that to the possible number of objects that could comprise the map, I figured the truly easiest way to handle things is to broadcast a “clear all dynamic objects”-message. I’m surprised this took me so long to think up.