Python: Getting an reference from path for an actor in a sublevel?

Hello,

I’m working on an editor tool and I’m trying to get an actor reference from a actor path.

According to the Python documentation I can use unreal.EditorLevelLibrary().get_actor_reference(path) for this.
It works fine for anything in my persistent level, but always returns None when trying to get something from a sublevel.

Say I have 2 objects (ActorA,ActorB), one in the persistent level (MAP_Persistent)(ActorA) and another in a sublevel (Map_Art)(ActorB).

If I get the paths for these actors I get something along these lines:

MAP_Persistent.MAP_Persistent:PersistentLevel.ActorA

Map_Art.Map_Art:PersistentLevel.ActorB

If I use unreal.EditorLevelLibrary().get_actor_reference(“PersistentLevel.ActorA”) it works completely fine.
However I’m struggling getting a reference for Actor_B.

I’ve tried:

unreal.EditorLevelLibrary().get_actor_reference(“PersistentLevel.ActorB”)
unreal.EditorLevelLibrary().get_actor_reference(“Map_Art:PersistentLevel.ActorB”)
unreal.EditorLevelLibrary().get_actor_reference(“Map_Art.Map_Art:PersistentLevel.ActorB”)

All of these return None.

I’m guessing this is related to the editor world. The documentation lists that get_actor_reference searches the current editor world. But isn’t my sublevel also part of this world?

How do I go about getting a reference from my ActorB? Am I missing something?

1 Like

I’ve met this problem as well, and finally figured it out. Since this topic is the top search on google, wish the answer could help you and future others.

For the record I was working on a project based on 4.24. Have no idea whether new version Unreal has tackled this problem or not. Personally I think they should since the new world partition works based on the “one actor per level” policy, but I understand this may not be of top priority.

Quick Answer


Don’t use unreal.EditorLevelLibrary().get_actor_reference(path).

Make your own editor module/plugin, and put the following code there(you don’t have to use my naming convention):

AActor* MyEditorFunctionLibrary::GetActorReferenceFromPathName(FString PathToActor)
{
        #if WITH_EDITOR
        return Cast<AActor>(StaticFindObject(AActor::StaticClass(), nullptr, *PathToActor, false));
        #else
        return nullptr;
        #endif //WITH_EDITOR
}

Then you can use your full path name (actor.get_path_name()) to access the actor.

Reason


The problem comes from the outer object.
Take a look at the UEditorLevelLibrary::GetActorReference function:

AActor* UEditorLevelLibrary::GetActorReference(FString PathToActor)
{
        return Cast<AActor>(StaticFindObject(AActor::StaticClass(), GEditor->GetEditorWorldContext().World(), *PathToActor, false));
}

the second argument is the outer object. Here it is kinda assumed that since you are working in editor, you should be using the EditorWorldContext().World(), which knowing through the debug info, is the persistent level.

In your example, your ActorB’s outer is Map_Art, but here the function puts your persistent level ( in your case MAP_Persistent) as outer, it can not find the target actor.

Key concept: by given the outer object, it (from my understanding) stripe out the package name part of the path, and try to combine what remains with the given outer object’s package. So no matter what you put, the closest it can ever find is MAP_Persistent.MAP_Persisten:Persistent.ActorB.

Of course you can not find it, since the ActorB lives in Map_Art.

In my given function, the second argument is nullptr, which means we don’t push any outer object into the function. By doing so, it would try to use the full path (that’s why you should use actor.get_path_name()) to search among all loaded objects in memory.

Since you’ve already loaded the level, all level actors among all levels belongs to the map has been loaded. Then you would be able to use the path name to find the actor living in levels other than the persistent level, since it’s been loaded already into the memory.

Personally I feel that the path name is a somewhat misleading name. It’s very natural to think the way you have thought before, since I did the same. But sad answer, no. Path name can’t be used on persistent level to find actors living in other levels, even though they have somehow bundled together in the level editor.

5 Likes