Creation of levels via C++?

As the title suggests, I’m looking to create levels for level streaming from C++. I’ve had a look at ULevelFactory, but it doesn’t seem to be the culprit.

What’s actually creating the levels when an in-editor user selects the option to add more streaming levels in the ‘Levels’ window?

Take a look at either “EditorLevelUtils::CreateNewLevel” or “EditorLevelUtils::AddLevelsToWorld”

I was just about to come back and suggest these :stuck_out_tongue: Finally found the ********!

Thank you, though. A potential life-saver :slight_smile:

Scratch that - I can successfully create levels, but if I specify the name myself (even with L"Game/Levels/ at the front), when they’re created, they work, appearing in the content browser and ‘Levels’ window. Even if I save them, when I close out of the level and return, all of those new levels are gone from the content browser, and the original level fails to load these streaming levels. Is there something that must be done to keep content browser assets from being cleaned up?

Sounds like the original World they are being created into is not being saved. You might want to try <YourWorldPtr>->MarkPackageDirty(); and see if that marks the main level as requiring saving. If that doesn’t work, then im not sure.

So I did some digging and figured it out. When you pass a name into EditorLevelUtils::CreateNewLevel, it’ll pass that through to FEditorFileUtils::SaveLevel. If that function can’t deduce the package name, it’ll fall back to the supplied name and presume that it’s been saved before. This alternative code-path, for some reason, doesn’t actually save it properly. If you call FEditorFileUtils::SaveLevel directly, once you get the level back from EditorLevelUtils, you can provide no default name and it will instead be able to deduce the package name, and will thus treat it as if it’s actually new and in need of proper saving.

UWorld* editorWorld = m_editorEngine->GetEditorWorldContext().World();
	if (editorWorld)
		FString preppedName = L"/Game/Levels/" + a_levelName;
		ULevel* level = EditorLevelUtils::CreateNewLevel(editorWorld, false, ULevelStreamingKismet::StaticClass(), preppedName);
		if (level)
			/* manually save after creation once the level has a name, so we don't have to specify one, and thus we
			still get the proper file saving path (as if the user was prompted). */
			return level;

	return nullptr;