Asset loading shenanigans (A python meta question)

In CaveX16, I had the messiest file in existance. One of the things this included was a list of blend files that needed to be loaded:


TILE_BLENDS = [
     'Models/UI/Indicators.blend',
    'Models/Map/Tile.blend',
    'Models/Map/Crystal.blend',
    'Models/Buildings/Concrete Pad.blend',
    'Models/Buildings/Light Tower.blend',
    'Models/Buildings/Entry.blend',
    'Models/Units/Miner.blend',
    'Models/Units/Resource Transport.blend',
    'Models/Units/MiningMachine.blend',
]

Now, this is one way to do it. It worked, but didn’t quite seem right. It’s a list that needs manual maintinance, and as can be seen from it’s name, it got, well, extended beyond it’s initial purpose.

Solution 1: Load everything in a subdirectory
There’s a Models folder, so why not just go through and load every item from in there? What if it is a big enough game that not all levels require all objects, then it becomes a waste of time/ram.

Solution 2: Load some objects using method 1 and others by parsing the level file
Have one subfolder for ‘generic’ objects needed all the time. Then have the level file define what addional assets are required (from presumably a different directory).

Solution 3: Each script tells the loader what it requires
In one of my non-bge games I did this. I created a global-namespace function so every script could call “requireObj(path)” and then the loader would know it needed to load that data file. This worked really well in Javascript, but in python it will require a circular dependency as most python files will need to import the load script to register these object with them.
This handles different levels easily as you can just call requireObj from when the script is initialized but before the loader runs. This is how things were handled in Simple Six.

Solution 4: Python Meta-magic
Yeah, nope. Not going here. Anything involving magic dictionary lookups, parsing module code etc. I will not consider without an extremely compelling argument.

So how have people handled loading assets in the past, or a I the only person actually using LibLoad in my games?

what about getting all .blends in a sub directory and then looking for a prefix

LoadMe1_castle.blend
LoadMe1_beach.blend
LoadMe1_Sprites.blend

LoadMe2_island.blend
LoadMe2_city.blend
LoadMe2_Sprites2.blend
??

This isn’t an issue with loading order or deciding which assets to load. This is about figuring out where the information abotu what needs to be loaded should be stored.

Original Solution: The “Game” knows what to load in all cases
Solution 1: Just load everything (bypass the problem)
Solution 2: Load everything necessary, and then look in the Level file for more information
Solution 3: The pythonic object/module knows what models it depends on
Solution 4: ??

I usually have all the things I need for a level in one blend and organize my games that way.
It’s a nice idea to only load the individual items that are needed, but there’s more chance of things going wrong when you have lots of files. The overhead in having all weapons loaded or all low level monsters is not that high…

In cave x16 I would guess that all levels would require concrete pads and light towers, so there’s no need to load them individually. Maybe you want a certain flavor of objects for certain tiles (like ruined concrete pads or barbed wire towers) in that case you would make a set and import it.

Remember paths are strings so you can use format:

asset_path =  "models/level_assets_{}.blend".format(self.level_number)

to load the assets required for the current level.

If I want to load only the required monsters I might give each monster type a category which is returned when loading them as a mob:

def spawn_mob(self,level= "RANDOM"):
    ...
    return mob_level

mobs = [self.spawn_mob() for i in range(16)]

monster_levels = ["high","medium","low"]

for level in monster_levels:

if level in mobs:
    load_monsters(level)

The mobs aren’t actually the agents, so they don’t require any assets at this point, they are only structures used for spawning individual enemies in the next few tics.

My main game loop is a FSM so it has a few different states it goes through while preparing the game for play. This can be important because some things can’t be referenced in the same frame they were created and so require a delay before you can bring them online properly.

There might be a LoadLevel state, and SpawnMobs state a SetFilters state etc… This can be useful too for showing loading progress.

What is the real basic of your requirement?

I think you can reduce it to this question:
WHEN to load WHAT?

Typically there are mean answers as there are many situations.

Each single WHEN can be require a different WHAT.

I guess you want something like a LOD or Occlusion. The WHEN reduces to:

  • load right before the camera can see the objects.

Typically the camera enters a certain area -> WHEN.
In this situation a connected area might become visible moving the camera. So you want to load the assets of that connected area. This is the WHAT.

LibLoad allows to load meshes from a blend file. This requires:

  • the name of the blend
  • the name of the mesh(es)

LibLoad allows to load all objects of a scene from a blend file. This requires:

  • the name of the blend
  • the name of the scene

I guess this is where you currently are. You need a way to get this information somehow.

The BGE API does not help. There is nothing to explore blend files.
The Python API allows to explore the file system. This helps to get the name of the blend file. You still need a way to identify the right one.

Here are my suggestions:

A) Identification by convention:

  • you can calculate the blend file name from the current game’s state. E.g. you want to load area x:20, y:13: so the blend file name is: “area_20_13.blend”
  • you can calculate the scene’s name from the current game’s state. E.g. you want to load area x:20, y:13: so the scene name is: “area_20_13”, or (other example) it is always “Scene”
  • additionally you need to calculate the name of the library (for later unload).

B) Identification by configuration

  • This is what you described in your top post. You get configuration that you access with the current game’s state. The configuration provides you with the blend file name, scene name and library name. This is more or lass a special form of A).

Where to get this configuration from?

  • read it from a python file
  • read it from a configuration file (text, ini …)

How to create this configuration?

  • Manual creation
  • automatic geration via Blender script