I originally approached this problem using Blueprint because I felt it might be a good exercise for me to get more familiar with Blueprint. It seems apparent now that what I am trying to do isn’t possible in Blueprint, so I’ll give it a shot here instead.
To put it as simply as possible: I want to create some actor instances and add them to the level when a level is loaded.
The goal being to dynamically create some actors, which are not saved in the level data, and have them appear in the level as if they had been hand-placed in the level. This means they should appear in the level when it is loaded in the editor as well as when that level is loaded in the game. For this reason, spawning actors in response to BeginPlay or similar events is not a viable option.
I’m an experienced C/C++ programmer, but my knowledge of the inner workings of Unreal is pretty much non-existent. This is my first attempt at any Unreal hacking. I’ve been stepping through the code in the debugger, and can see some opportunities for where this might be possible. But not being experienced with Unreal, I’m not sure where the “correct” place to do this would be, and what the “correct” way to create these actors would be so that they are treated just as any actor that had been placed in the level.
Any advice would be greatly appreciated, as long as that advice does not suggest to use BeginPlay
Thanks in advance!
(for reference, the thread where I posed this question using Blueprints is here.
Spawning actors isn’t the part that I’m having a problem with. Figuring out where in the code to spawn those actors to get the behavior I want is the thing no one seems to be able to answer. Again, any answers related to BeginPlay or similar events are not what I am looking for - see the requirements in the first post.
Have you looked at FWorldDelegates::OnLevelChange event? It’s defined in Engine/World.h and called from the UWorld class. I would try adding code to set it up in your Game Module constructor, which is called during pre-init and see if you get a call at the right time.
You may also be interested in looking at the ChildActorComponent.
Dynamically spawning a transient Actor when loading the level for gameplay should be relatively straightforward, however, to do so in the Editor is going to be quite problematic. Once the Actor is spawned it is a member of the Level’s Actor array and will get saved out. In theory (in C++ only) you could add RF_Transient to the ObjectFlags for the FActorSpawnParameters that are passed to SpawnActor and that Actor will not get saved out, however, you may find that you can get problematic set ups that way, for example if you attach a persistent Actor to the transient one. In general I would not recommend this approach and would be curious what goal you are trying to accomplish with it.
I have a database on a network that contains meta-data associated with each level in my game. A level in my game is a combination of the content hand-crafted in the Unreal editor, and content created dynamically at load-time based on the meta-data stored in the database. I access the meta-data in the database using a plugin to Unreal.
When I load a level in the Unreal editor, I want the dynamic content to exist in the map alongside the hand-placed content. It is even OK to manipulate the dynamic content just as you would any hand-placed content (depending on what properties get changed, I will either ignore the changes or communicate them through my plugin back to the database).
When I play the game, as in the editor, the dynamic content should be created and exist alongside the hand-placed content.
So the flow I am trying to achieve any time a new level is loaded in the game or editor is:
Load Unreal data.
Generate additional actors in the level based on query results.
In terms of injecting your actors when the level is loaded I think you’ll want to look at attaching delegates to FEditorDelegates::OnMapOpened and FCoreDelegates::PostLoadMap. The editor one is called when the map is opened, the core one when a map is loaded for gameplay. You’ll probably need to be careful to avoid duplication in the Play in Editor case.
There is also a FEditorDelegates::PreSaveWorld which may be relevant to your needs for updating the state of the actors when the map goes to be saved. As I mentioned previously I think to avoid the Actors being saved out you’ll want to flag them transient when you spawn them. Another alternative would be to allow them to get saved, but strip them out/update them in the OnMapOpened to pick up updates. The nice thing about this approach is it means that when you cook your final level you’ll have the actors in place as I imagine you don’t want to be referencing the DB to place these actors in a final build.
I myself am interested in this right now since I’m experimenting with random level generating.
I could create the level on game start, but I was thinking about creating the level on level load so I get more control over certain things, and then also dynamically spawn volumes for navigation, etc…