Is it possible to create a new Level (so a new .umap file) directly from C++ code, for example from a plugin’s code ? I would like to automate the level creation (not having to go through the editor => new Level menu) then populate it directly from code, without having to interact with the editor whatsoever.
Yes! I had to do this as part of my plugin (although I create a new UWorld not a ULevel).
The way I did it was by creating a template world in my plugin’s Content folder (with basic things like a Light Source and Sky Sphere) and then copy that for each new level. Here’s the rough code I used:
auto WorldTemplateObj = StaticLoadObject(UWorld::StaticClass(), NULL, TEXT("World'/MyPlugin/LevelTemplate.LevelTemplate'"));
ObjectTools::FPackageGroupName PGN;
pgn.ObjectName = MyNewLevelName;
pgn.PackageName = MyNewPackageName;
TSet<UPackage*> ObjectsUserRefusedToFullyLoad;
auto World = CastChecked<UWorld>(ObjectTools::DuplicateSingleObject(WorldTemplateObj, PGN, ObjectsUserRefusedToFullyLoad));
Alternately, you can instead use UWorld::CreateNewWorld, which will give you a truly clean world.
Thank you, worked perfectly !
Any idea how I could go about opening the level in the editor via the C++ code though ? The level properly appears in the content browser (as unsaved though) but my editor still has the previous level opened. Do you know how I could open the new one that I just created without having to double click on it in the assets browser ?
I too am unclear on how to open a World without user interaction. It looks like you might have to use FEditorFileUtils::LoadMap, but the code within looks very thorny.
And it’s not working. I suspect it’s because the Shot_42 map (that I created thanks to your technique !) hasn’t been savec/serialized to a file yet. So, I looked further and found this :
That’s a linker error, so usually, it would mean you forgot a module in your build file but it doesn’t here. In this case, looking at FileHelpers.h, it looks like SaveMap is missing its API SpecifierUNREALED_API. Compare the following declarations:
I think this is a mistake by the Unreal dev team. A possible messy workaround would be to copy the implementation from FileHelpers.cpp into your own file but this may be infeasible, depending on how many private properties it uses.
An easier route (if it works, I don’t know) would be to save the Persistent Level, FEditorFileUtils::SaveLevel(World->PersistentLevel,FileName), which should create a
Sorry for the late answer ! Perfect, I used your easier route and it worked just fine. I called the method without a FileName (because it would crash, for some reason, or not save the map at the right place) and it saved it with the right name where I wanted, which is great. I could then LoadMap and it worked !