Programmatic (not procedural) Level Creation

Hello. I wanted to create a level using data I have on rotations and locations of some actors. Sort of like importing a terrain heightmap.

For example I have 1000 wall pieces that will each use a random texture (from a set of textures) and I have already generated the placement using an algorithm outside of UE4 (I have data containing rotations and locations of each piece). I don’t want to manually drag each actor into the level, assign it the texture and transform.

How would I do this programmatically?

I want the level to be built once and have it stay the same for every player who ever uses it so it doesn’t need to be procedural or change ever again.

Thank you!

You need to write editor plugin that creates static mesh actors within current level.

Here’s related question on answerhub:

https://answers.unrealengine.com/questions/246723/addactor-in-the-editor-via-c-module.html

Basically, GEditor->GetEditorWorldContext().World()->SpawnActor… (op in the question used AddActor, but spawn works just fine).
Followed by actor setup (static mesh component, etc), followed by

AStaticMeshActor->MarkComponentsRenderStateDirty();

Thanks! That makes wonderful sense. Now I need to learn how to do that lol

Any great tutorials come to mind? I found a few already but none seem to be great and if you know any off that top of your head that would be awesome. If not thanks for pointing me in the right direction! :slight_smile:

No, I can’t think of any (they might exist, it is just I am not aware of them).

Most of tutorial stuff covers blueprints, I was programming in C++, so I picked most of the info by reading/scanning through engine source code.

You don’t really need a plugin for that if you don’t want to make one.
You can do it through one actor’s construction blueprint graph. Every time you create/place an actor or change any of it’s params, the construction graph is executed.
Your external data, you can import as CSV data, just need to create an importer struct in C++ for it then you can use anyway you’d need them.

So you are saying in an actor I can cause it to create items that would permanently exist in the level? There is no spawn actor function available in the construction blueprint. Am I missing something?

I tried for a while and can easily make it spawn on begin play and do everything I want but then of course when the level ends none of the objects still exist in it. I also did it in the construction script by calling a function which spawns the actor but I couldn’t get it working. Can you clarify?

I’m guessing spawn is the wrong path to follow because that would only create objects when the game is running.

He was talking about spawning objects while the game is running.

Actor spawned from within editor plugin will stay on the map, well, unless you forget to save the map. It is the same thing as adding them manually.
Actor spawned while the game is running will disappear when you reload the level.
However, you could store list of actors to spawn in external file/resource and implement their persistence this way.

Potential issues:
Last time I checked, you can’t bake lightmaps into objects you spawn at runtime. No such problem when spawning stuff from editor plugin.

Also, when spawning large number of objects into editor (5000 of them) I encountered minor issue where you’ll encounter significant fps drop (down to single digit framerates) right after spawning objects, and fps loss will stay until you press “build” button (meaning it is instantly fixable). After that fps goes back to sane level (60…70). I’d guess you’ll get the same issue if you start spawning lots of objects at runtime, except that there won’t be a “build” button to press.

Excellent. That is what I thought but I wanted to investigate a little further before embarking on the build a plugin adventure :slight_smile:

So I was cruising around learning stuff for about two hours, almost had a blank plugin running (I think). Then I saw this button:

Haha, easy mode activated :slight_smile:

So easy mode is not so easy!

I’m not sure what I am doing wrong. I cannot at all succesfully replicate what was in this post that was linked above:
https://answers.unrealengine.com/questions/246723/addactor-in-the-editor-via-c-module.html

I’ve tried many variations of GEditor Getworld and GetEditorWorldContext and SpawnActor and Actors.Add and AddActor. I have tried loading the level and adding objects to it. I stopped receiving errors at a certain point and now am just trying random things but nothing appears! I have tried adding it as AActor and as UClass. Loading it with and without the _C and many combinations.

If I do this I get nothing in the logs but nothing happens.

UClass* LevelPieceObj = LoadObject<UClass>(nullptr, TEXT(“Blueprint’/Game/Levels/SurfaceChunk.SurfaceChunk_C’”));
GEditor->GetEditorWorldContext().World()->GetCurrentLevel()->Actors.Add(Cast<AActor>(LevelPieceObj));

With this it triggers a breakpoint:
UClass* LevelPieceObj = LoadObject<UClass>(nullptr, TEXT(“Blueprint’/Game/Levels/SurfaceChunk.SurfaceChunk_C’”));
GEditor->GetEditorWorldContext().World()->SpawnActor<UClass>(LevelPieceObj, FTransform(FVector(0)));

In Casts.cpp and tells me

“Cast of
FromType 0x0000000011e6f000 L"SurfaceChunk_C /Game/Levels/Level1.Level1:PersistentLevel.SurfaceChunk_C_0”
to
ToType 0x0000000021a1bac0 L"Class"
failed"

I’ve tried many variations but I either get cast failures, it cannot find the object, or nothing happens at all (no logs, nothing).

I haven’t found any other examples of this that work for me and would love some help if anyone sees what is going wrong!

Nope;
I was talking about creating an empty actor as a parent just to use its construction script, like this:

Haha that makes sense and is super easy :slight_smile:

I put 100 columns along the edge of a circle as a test:

I would still like to figure out the other way so I can manipulate the individuals actors in the level if I need to but this will work for now :smiley:

Thanks!

Update on Implementation:

I’m still using the constructor with child actors. The time it takes doesn’t seem to scale linearly and I capped it at 400 per actor (started at 2000 and ended up killing the editor process). I think this is because it is difficult to control when the constructor fires so you may end up creating and destroying thousands or tens of thousands of actors for each 100 you are creating.

I only need one or two per level though as I will stream them so I imported the data in one giant chunk with an indexing column I use in each actor that says if == yourNumber then make this child actor. Then I drag each spawning actor into its relevant level. It all works well for the moment but feels a bit hacky. Since implementing the C++ plugin method should yield identical results I can go ahead with other design stuff until I figure the C++ method.

Thanks everyone for your help!

Now, does this properly work with lightmap baking and occlusion culling?

No idea. I’m actually doing paper2d stuff. It’s still somewhat frustrating and I would love to be able to figure out the C++ method but this at least lets me continue working.

Why would it break lightmaps? They’re still just actors, but attached to a lead object.

Did you check this page? Creating Objects in Unreal Engine | Unreal Engine 5.3 Documentation
Use Class::StaticClass() to create the object.

Because the first thing I tried when I installed ue4 was attempt to build level with modular blueprints. Lightmaps did not bake for blueprinted actors and were marked brown in lightmap density view. ( Viewport Modes in Unreal Engine | Unreal Engine 5.3 Documentation )

Now, does that work with lightmap baking?

I don’t know, would have to try; If it doesn’t work there’s there something the engine could improve I guess.

Edit: yep, seems Epic have it planned, but didn’t implement yet, found a post from Staffer:

If anybody still passes by this thread, know that I’ve solved this using “Editor Utility Blueprints” Scripting the Editor using Blueprints | Unreal Engine Documentation

There you can set the creation script as a Blueprint and call it with a button. For example, in my case I’m spawning N bluprinted actors at random positions.

You can also make another button to destroy them.

Might still not be the same as handspawning them because when deleted the editor complains they are still referenced by my spawning actor, but it’s pretty neat.