Can Level Instances have exposed variables?

I’m using level instances like a meta-blueprint to avoid using child actor components, an elevator in my specific case. But now running up against the problem of figuring out how to allow for distinct behavior per level instance. I’d like to be able to support elevators that can have different setups in terms of where they travel and I’m trying to figure out the cleanest implementation.

I might just make an external blueprint that manages each one but has a reference to the individual level instances and try to do it that way. I just tried having an actor within the level instance try and access the parent but it’s returning None for some reason, going to dig into this more. I was hoping maybe I could attach a component on the level instance actor and access it from the level’s children.

Would be amazing if level blueprints for the instances could expose their variables in this way, but doesn’t work.

Open to any ideas!

That’s a tough one. I’ve done an insane amount of testing on loading levels including Level Instances and nothing is simple or easy. In theory, once BeginPlay is called, you should be good to go, but each actor is called in random order. I also don’t know how to get a Level Instance from an actor without iterating over everything.

Note that Level Instances aren’t loaded and displayed right away in a production build. Embedded Level Instances are a weird beast. In the editor, they’re not even in a LevelInstance. They’re in the main level itself because they’re preloaded. But in a production build, they’re in the Level Instance.

There is a LevelInstanceSubsystem. From that, you can get all the Level Instances. And you can even call LIS->ForEachActorInLevelInstance(LevelInstanceActor, lambda) to iterate over each actor in a level instance. Make sure to skip over WorldSettings actors.

When you say you have an actor in a Level Instance and you tried to access a “parent”, what parent are we talking about here? The Level Instance? Or is it attached to another actor?

The biggest problem you’re gonna have is knowing when a LevelInstance is loaded. If you use a Dynamic Level Instance, this is actually easier because you can manually load it and attach a delegate to the OnLevelShown event. But for embedded LevelInstances, there is no such possibility and it’s REALLY difficult to know when it’s done loading.

I have a writeup here if you want to know more about how levels load.


My advice would be to use a dynamic streaming level instance. IOW, load the level instance manually. Then you can attach a delegate to the OnLevelShown event. Then you can use your own function or BP event to do the setup you want. You have the Level Instance because you loaded it manually. So you can use the LevelInstanceSubsystem to iterate over the actors in the level instance and find the actor with your setup BP if you want to do it that way (or just have everything in the original BP or function).

1 Like

Appreciate the detailed response. Basically I have a scene with 2 elevators and I want to reuse the same logic, but have them travel to different levels. So I was hoping to find a way to be able to, at a minimum, give each one some kind of ID so I could identify which elevator connects to which levels and modify the art/etc. Each elevator contains multiple other blueprints within it and I plan on re-using this same big asset throughout the game.

Through a little bit of digging I noticed that in editor settings there is a checkmark for an experimental feature called ‘Enable Level Instance Property Overrides’ so I assume someone at Epic at one time at least tried to get this working. I read over discord that this has been abandoned for being too buggy, which is a shame. From what I gathered through researching is that Epic plans on implementing SceneGraph in the core engine (like they do in UEFN right now) at a future date which will kind of change how scenes work more fundamentally, but this also feels like rumor mill type inormation.

One thing I was planning on doing was defining an actor component on the level instance actor that would contain whatever data I would want to reference per instance. The instances themselves contain a manager blueprint that I was hoping to be able to do like manager->GetParent()->GetComponent< LevelInstDataComponent >(). But calling GetParent returns null for the actor and GetOuter returns the persistent level in my case, so it seems like it just gets injected into the scene like you were saying. I tried both settings on the level inst actor for level behavior, Embedded and Standalone. I also tried to go outside in to set the data, but there’s no clear method of accessing a level instance actor’s spawned actors. I didn’t want to just go the route of searching all the actors with the scene and determining via location within the map or all actors within a volume or something weird like that.

For now I just remade it as a blueprint containing child actor components and am just dealing with that. The idea of just manually streaming in a level instead of relying on the level instance actor makes sense too. I’ll check out your post to learn more as well, thank you!

When you say “level instance actor”, do you just mean an actor in the level instance or do you mean the actual level instance actor itself? When a Level Instance is loaded, there is a placeholder actor that is of type ALevelInstance. It’s an actor that takes the place of the level instance during initialization. But I suspect this isn’t what you’re talking about. From your phrasing, it seems like you just want an actor in your Level Instance that handles setup. Could you clarify which one you are using?

What type is the manager? You said it’s a blueprint. What kind of blueprint? What’s the base class? You said GetParent() returns null for the actor. Does that mean the blueprint was an actor or the return value was supposed to be an actor? Trying to understand the hierarchy.

If you’re trying to get a parent, I don’t understand how a BP would have one if it’s an actor. If you’re in a blueprint of an actor, SELF is the actor, not GetParent(). So you can just use manager->GetComponent() directly.


I played around a bit with Level Instances. Here’s something that may work. Suppose you add a few Level Instances into your level. In each Level Instance in the Outliner, go to the Actor subsection and add a unique tag. Make sure it’s in the Actor section, not the component one. Add something like Elevator1. In the other one, add Elevator2 tag. I think the Level Instances need to be Standalone.

Place a dummy actor in the main scene (not in the level instance). In its blueprint BeginPlay event, do a GetAllActorsOfClass with a class of LevelInstance. Then do a ForEach on the output. Grab the Tags. Check that it’s not empty and that the first entry starts with “Elevator”. If so, grab the index from the tag.

At this point, you’ll need some C++ since this function isn’t available in blueprints. You can put this as a static function in your custom GameInstance if it’s single player.

Then you can do something like this (static function):

AActor* MyGameInstance::GetSubLevelActor(ALevelInstance *LevelInstance, const FName &Tag)
{
  UWorld* world = this->GetWorld();
  ULevelInstanceSubsystem* LevelInstanceSubsystem = 
  UWorld::GetSubsystem<ULevelInstanceSubsystem>(world);
  if (LevelInstanceSubsystem)
  {
    AActor *LocalActor = nullptr;
    LevelInstanceSubsystem->ForEachActorInLevelInstance(LevelInstance, [&LocalActor](AActor* Actor)
    {
      // Ignore World Settings.
      if (Actor->IsA<AWorldSettings>())
        return true;

     if (Actor->AghocHasTag(Tag))
    {
      LocalActor = Actor;
      return false;
    }
    
    return true;
  });

 return LocalActor;
}

The tag you pass in is a tag for an actor inside your LevelInstance where you want to set an ID or something.

So in your blueprint, you call this function with your LevelInstance from above. And the Tag would be something like “ElevatorActor”. Make sure this tag exists on the actor (inside your level instance) where you want to store the ID.

So with the returned Actor, you would set the ID on it. You will have to cast or use an interface. If you cast, make sure the little eyeball is on next to your ID variable.

Now that the ID is set, your blueprints in your Level Instance can go different height or do different things based on this ID.

A bit of warning though. Don’t put lighting or navigation in any Level Instances or Streaming Level.