Dynamically Spawning and De-spawning Lights

Hey. This is a simple little trick to de-spawn and re-spawn lights in-game; I never really wondered about this myself too far, but I just now thought about the possibilities of deleting and spawning lights dynamically in-game. So, I thought I’d make a note here about my quick findings in case someone wanders along wondering about it.

  1. You can delete lamps in-game to reduce the load on the Rasterizer. Lamps don’t take up FPS while they’re not spawned (unsurprisingly), so a simple trick to having nice dynamic lighting would be to delete lamps that you’re far away from or looking away from.

  2. You can spawn lamps in-game when you need to. Note that there are a couple of rules to this.

    Rule #1. You can only spawn a single lamp once. If it exists in-game already, then you can’t spawn it again.

Rule #2. The lamps need to be in a hidden layer in the same scene that they’re going to be added into in-game. If they’re in another scene (or blend file, I suppose) and linked in via group instances, the process won’t work (they can be added in, but they won’t light the scene).

The solution to spawning a lamp once would just be to create multiple lamps in a hidden layer, and then spawn one that hasn’t been used yet. Of course, this is something you can do with Python. Also note that once a lamp is deleted, it can be re-spawned. So, a pretty simple Python script can just keep track of lamp objects that have been created already and choose one that isn’t already in use when light spawning is needed.

Here’s a blend file to show the example of spawning the lights dynamically in-game, and with that light registry Python script. A good thing about it is that there shouldn’t be any necessary tricks if you want to delete a light. Just delete it, and when you go to re-spawn another one, the script will re-use that light if necessary. I encapsulated the script into a Python function that can easily be adjusted to allow for adjustable color, energy, etc. as necessary.

Note that there is very little performance gains in my example, as they’re just point lamps.

Here’s the blend file.

Very nice! I was thinking recently about a shadows LoD (generally lamp lods), I know this couldn’t be done with kupoman’s lods since it isn’t a mesh. but is there any other lod system that works on a separate thread and works for non-mesh objects?

I would have sworn it was possible to spawn several points with just one point … :confused:
I had to be somewhere else that day!
In any case, very good script, it is a pity that’s not possible to do it with a single point :stuck_out_tongue:

//sorry for my bad English level :o//

@Jackii - No, I don’t believe so. If you wanted a LOD system for shadows, it should be possible with this method and spawning lights with shadow buffers of different size. It’s worth a try, at least.
@Lake - Yeah, it’s kind of unfortunate, but at least there’s a workaround.

Today I was trying to figure out why this method wasn’t working for me with Valchion. I found that the lamps have to be in the same scene as they’re being added into to light the scene correctly.

EDIT: Updated the SpawnLight function to change the name, return the added light, and only pull from lights that have game properties of the name “Dyn” + type, like “DynPoint”, “DynHemi”, “DynSun”, and “DynSpot”. Also, it only takes the kind of light you want to spawn as an argument now. Here’s the updated function (the blend file from above isn’t updated).



def addLight(light_type = 'Point'):
    
    sce = logic.getCurrentScene()
        
    obj = logic.getCurrentController().owner
      
    if not hasattr(logic, 'lights_used'):
       
        logic.lights_used = {
        'Point':{}, 
        'Sun':{},
        'Hemi':{},
        'Spot':{},
        } # Create a mapping of lamps with their types to spawners
            
        for lt in logic.lights_used:
            
            for l in [l for l in sce.objectsInactive if "Dyn" + lt in l]: # Loop through the lamps that have the type in their name (i.e. Point lamps named "Point", "Point.001", etc.)
                
                logic.lights_used[lt][l.name] = 0 # And set their "used" status to 0
                
    for l in logic.lights_used[light_type]: # Then loop through all of the lamps
        
        if logic.lights_used[light_type][l] == 0: # And when you find a lamp that hasn't been used
            
            light = sce.addObject(l, obj) # Create that lamp,
            
            logic.lights_used[light_type][l] = 1 # And set it to be used (mitts off to all other spawners until it's destroyed)


            return light # And then break out of the loop, returning the spawned light
          
        else:
            
            if l not in sce.objects or sce.objects[l].invalid: # If the lamp you've "found" is used, but doesn't exist or has been deleted,
                
                light = sce.addObject(l, obj)
                            
                logic.lights_used[light_type][l] = 1 # Then re-use that one, rather than looking for another lamp
                
                return light # And then break out of the loop, returning the spawned light


Very good investigation!
That will become useful.


I could not help myself.