添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
茫然的登山鞋  ·  Help in ORA-01741: ...·  3 月前    · 
完美的脸盆  ·  Resolve timestamp ...·  11 月前    · 
愉快的单车  ·  Developer Community·  1 年前    · 

Greetings,

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.

How can I do that ?

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 ?

That looked promising, but I tried this :

FEditorFileUtils::LoadMap(TEXT("World'/Game/Scenes/Shot_42.Shot_42'"));

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 :

FEditorFileUtils::SaveMap(World, TEXT("World'/Game/Scenes/Shot_42.Shot_42'"));

However, I’m getting a compilation error :

Module.ImportIntoLevel.cpp.obj : error LNK2019: unresolved external symbol "public: static bool __cdecl FEditorFileUtils::SaveMap(class UWorld *,class FString const &)" (?SaveMap@FEditorFileUtils@@SA_NPEAVUWorld@@AEBVFString@@@Z) referenced in function "public: void __cdecl FImportIntoLevelModule::PluginButtonClicked(void)" (?PluginButtonClicked@FImportIntoLevelModule@@QEAAXXZ)
1>D:\Unreal Projects\PythonPluginTest\Plugins\ImportIntoLevel\Binaries\Win64\UE4Editor-ImportIntoLevel.dll : fatal error LNK1120: 1 unresolved externals

I don’t understand why I’m getting this error while FEditorFileUtils::LoadMap works perfectly. Any idea ? And thanks for your help :slight_smile:

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 Specifier UNREALED_API. Compare the following declarations:

static UNREALED_API void LoadMap(const FString& Filename, bool LoadAsTemplate = false, const bool bShowProgress=true);
static bool SaveMap(UWorld* World, const FString& Filename );

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 !

Thank you again :slight_smile: