[Question] Best UE4 C++ way to determine which Streamed Level a Physics Actor is in?

Dear Friends at Epic,

What is the most efficient C++ way to determine which streamed level an actor resides in?

I am talking about a static mesh actor that is simulating physics!

I can get the current location of the simulating static mesh actor.

But how do I know which level it is in, since it could easily cross the various volumes for streamed in levels?

Rama

I assume based on your comments you have found something that works for you. I’d like to mention a couple things that may or may not help you or someone else finding this thread:

Resides in is a bit of a vague term. All placed Actors are members of that Level. Calling GetLevel() on them will give you a reference to the ULevel, from there if you wanted the ULevelStreaming you can call FLevelUtils::FindStreamingLevel.

A dynamically spawned actor will, for the most part, be spawned in the persistent level. If by resides you mean, as it seems you did, which level does the location of the actor best map to, you can take the approach you have but you should keep in mind it is completely valid, and in fact common at the connection points for the level bounding boxes to overlap not insignificantly as well as in situations a large level that defines say the vista with smaller rooms that are brought in and out, for the level bounds to overlap each other.

“A dynamically spawned actor will, for the most part, be spawned in the persistent level.”

This was very useful information for me, thanks Marc!

Great to hear from you as always!

Rama

For anyone who ever needs this info:

In world.h is a list of all streaming levels
/** Level collection. ULevels are referenced by FName (Package name) to avoid serialized references. Also contains offsets in world units */
UPROPERTY(Transient)
TArray StreamingLevels;


In each ULevelStreaming is a function to get its bounds

/** Get a bounding box around the streaming volumes associated with this LevelStreaming object */
FBox GetStreamingVolumeBounds();

In Box.h

is a function to see if a FVector is within the box

Box.h
/** 
 * Checks to see if the location is inside this box
 * 
 * @param In - The location to test for inside the bounding volume
 *
 * @return true if location is inside this volume
 */
bool IsInside( const FVector& In ) const
{
	return ((In.X > Min.X) && (In.X < Max.X) && (In.Y > Min.Y) && (In.Y < Max.Y) && (In.Z > Min.Z) && (In.Z < Max.Z));
}

Put it all together and you can test whether any point is within any level, any time, from GetWorld()


#ULevel::LevelBoundsActor;

#LevelBounds.h Function

	LevelBoundsActor.h
	/** @return Bounding box which includes all relevant actors bounding boxes belonging to specified level */
	ENGINE_API static FBox CalculateLevelBounds(ULevel* InLevel);

There is also this amazing function!

/** @return Bounding box which includes all relevant actors bounding boxes belonging to specified level */
	ENGINE_API static FBox CalculateLevelBounds(ULevel* InLevel);

:slight_smile:

Rama

ULevel::LevelBoundsActor;

#LevelBounds.h Function

	LevelBoundsActor.h
	/** @return Bounding box which includes all relevant actors bounding boxes belonging to specified level */
	ENGINE_API static FBox CalculateLevelBounds(ULevel* InLevel);

There is also this amazing function!

/** @return Bounding box which includes all relevant actors bounding boxes belonging to specified level */
	ENGINE_API static FBox CalculateLevelBounds(ULevel* InLevel);

#Complete Code Sample

This code determines whether the player is located within the bounds of a streamed in level

only works for levels that have any streaming levels :slight_smile:

//Level Bounds Test
		TArray StreamedLevels = GetWorld()->StreamingLevels;
		
		for(int32 v=0; v< StreamedLevels.Num(); v++)
		{
			if(!StreamedLevels[v]) continue;
			//~~~~~~~~~~~~~~~~
			
			ULevel* EachLevel =  StreamedLevels[v]->GetLoadedLevel();
			if(!EachLevel) continue;
			//~~~~~~~~~~~~
			
			//Is This Level Visible?
			if(!EachLevel->bIsVisible) continue;
			//~~~~~~~~~~~~~~~~~~~
			
			//Print Package Name For this Level!
			ClientMessage(StreamedLevels[v]->PackageName.ToString());
			
			//Is the Player Location Within this Level's Bounds
			if(ALevelBounds::CalculateLevelBounds(EachLevel).IsInside(VictoryUnit->GetActorLocation()))
			{
				ClientMessage("Yes Player Is Within This Level");
			}
		}