Python, create streaming level

Hey folks,

I was up against the problem of automatically adding existing levels, too, and I came up with a method. It’s probably not the most elegant method, but it does work. A note, though. There’s a function called unreal.EditorLevelUtils.add_level_to_world that only seems to work in 4.26. This whole thing is going to seem a little weird, but here are the problems I was working around that necessitated the strange approach.

  1. Levels in unreal aren’t assets, they’re objects. I couldn’t find anything that would return objects from a given directory.
  2. I could use os to get all the files in a directory, but getting the full path to the project required jumping through a few hoops.
  3. I always ended up with a \ in my file path. I couldn’t replace it with string.replace, so I had to split the string with , then join it back together with a /. Weird and a pain, but it works.

Ok, without further ado, here’s the script.

import unreal

import os

@unreal.uclass()
class levelUtil(unreal.EditorLevelUtils):
    pass

# This is the level that is currently open in the editor. This is where your levels will be added.
world = unreal.EditorLevelLibrary.get_editor_world()
# This boils down the currently open level to just the name. I use this later to make sure I don't try to add a streaming level into itself
worldSplit = str(world).split("/")
worldSplit2 = worldSplit[len(worldSplit) - 1].split(".")
worldTrack = worldSplit2[0]

# This is the directory where your project is stored.
projPath = unreal.Paths.convert_relative_path_to_full(unreal.Paths.get_project_file_path())

# I need the actual file path of the project, and since the "Game" folder is actually called "Content", this replaces "Game with "Content".
temp = projPath.rfind("/")
newPath = projPath[0:temp]
newPath += "/Content/"

# This is an array that will hold my levels.
maps = []

# This goes through the project directory and returns every file therein.
for root, directories, files, in os.walk(newPath, topdown=False):
    for name in files:
        # This is a file.
        asset = os.path.join(root, name)
        # In the end, I just need the relative path to the level, so this bit boils it down to just that.
        firstSplit = asset.split("/")
        checker = False
        mapPath = ""
        for bit in firstSplit:
            if checker:
                mapPath += "/" + bit
            elif bit == "Content":
                mapPath = "/Game"
        # This splits the file name at the "." and checks if it's a "umap" file type. If it is, it goes into the maps array.
        secondSplit = firstSplit[len(firstSplit) - 1].split(".")
        if secondSplit[len(secondSplit) - 1] == "umap":
            if secondSplit[0].find(worldTrack) == -1:
                maps.append(mapPath + "/" + secondSplit[0])

for map in maps:
    # I had a heck of a time replacing the \ with a /, but this seems to work.
    mapSplit = map.split("\\")
    newMap = mapSplit[0] + "/" + mapSplit[1]
    # This adds the streaming level to your currently open level.
    levelUtil().add_level_to_world(world, newMap, unreal.LevelStreamingAlwaysLoaded)

addLevels.py (2.2 KB)

1 Like