Download

How should I go about spawning and editing content in an un-streamed level?

This might be an excessively broad question, but it speaks to a really common problem I’ve had working with very large game worlds. Take, as a case study, my current problem: I have a procedural question generator that lives in the persistent level, and if it generates a quest to kill the unique bad guy in the haunted castle, that bad guy had darned well be there when I arrive. More to the point, he needs to be there consistently. Since the level itself is static, and resets itself every time it streams out, it seems like the only way to position him would be to manually stream the level in, place him there, and keep the level in memory until he’s dead, but that’s obviously ridiculous and wouldn’t scale at all.

Likewise, there are lots of cases where my generator needs to query a specific level in order to do things like “Determine how many buildings are in this chunk, and make one of them the quest’s next destination,” but any reference I make to the level’s geometry, or any unique components I add to quest-important objects, are going to get deleted and not re-created next time that level goes poof.

This seems like such a common issue that so many games deal with, is there a standard or recommended way to deal with what I’m discussing?

I would keep a lot of that sort of data in your GameInstance class. For the first example, you could have your game instance determine whether the boss needed to be spawned, and if so, spawns him on level load.

You also (or additionally) might consider a level manager class inheriting from LevelScriptActor; this could allow you to build a common interface to simplify the process of spawning dynamic quest-driven objects.

You might be able to subclass ULevel (or some other level-specific data storage system, say WorldSettings?) to store the requisite information for a level’s buildings or other needed data.

Hmm, could you expand on what you mean by creating a subclass of LevelScriptActor? Would the purpose of that be setting it up so every time a level streams into the world, it automatically runs whatever logic I want (like finding the world controller and asking for instanced/specialized spawns)? If so, is there any reason not to simplify it, and simply do that by having some kind of OnSpawn logic actor inside each level, that does the same logic in its own constructor?

The LevelScriptActor class is the C++ backend of the Level Blueprint. In essence, it is the world controller. You could set it up that when it streams in (BeginPlay), it queries your GameInstance or GameMode to get the requisite bosses or NPCs or loot or whatever to spawn.

I assume by OnSpawn, you mean on level load? That gets fired automatically as the BeginPlay function of your Level Blueprint (and the underlying TSubclassOf<ALevelScriptActor>).

Your Level Blueprint by default is inheriting from ALevelScriptActor, but can be reparented to a subclass.

That’s really helpful, thanks for the clarification :slight_smile:

Quite welcome.