However you see best.
Libload is good, but complicated, prone to human error, and has some bugs
Group linking is good, but you end up with group-owner-empties in your scenetree, and they don’t dynamically load.
Whatever you do: keep your scripts separate to your blend files. This will save you much pain when you accidentally hit ctrl+z with your mouse over the 3D view.
I’ve found I’ve had much luck using a code-first approach. Something in the code creates an object, and the implementation of the object spawns an entity into the scene. For example, in the code you may do:
c = Car(scene)
And then inside the object you may have:
class Car:
def __init__(self, scene):
scene.addObject("CarTemplate")
Often you can couple this with game properties and other odds and ends so that you can still use blender as a level editor. This also plays well with libload where you can have “dependencies” between implementations and their assets represented through the code. [One of my gripes about Godot is that it is nearly impossible to take this code-first approach, or maybe I just haven’t found out how yet]
Most of the time™ you don’t need libload. In the handful of commercial projects I did in the BGE, one had zero libloading, and one had about 5-6 blends loaded. (It switched blend into the level blend, then loaded a couple of assets). Rather surprisingly, the one with no libloading was the one with more data - hundreds of megabytes of assets. Yes, it still had a loading screen. Loading things from disk is frequently not what takes the time in a complex game. populating the world, setting up and compiling shaders and other things can take way longer.
My advice is: Don’t make things more complex than they need to be. If you can:
- Create groups of objects
- Link the groups into your level file
- Use the startgame actuator to that level file, or libloading that one file if necessary