Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

(UE4) Is there a method of getting all actors in camera view?

Like the title says, i want to be able to get all actors that are within the camera view in Unreal Engine 4.

I have thought of two ways i could do this: 1) using a shape trace in the form of a "boxtracebyobject" which works but seems to be glitchy at times and has trouble recognizing multiple overlapping actors. 2) using a "BoxOverlappingActors", though i havent quite figured out how to use it yet.

If anyone knows of a proper method to getting actors in cameria view, my ears are open!

like image 631
djs415 Avatar asked Oct 19 '25 14:10

djs415


2 Answers

Update

A much better answer has been posted on Unreal Answers by Rama:

Use the AActor::GetLastRenderTime() to find out for each actor when last drawn or UPrimitiveComponent::LastRenderTime for the primitive itself. His answer explains how you can use this.

Original answer:

As you suggested, it seems weird that you would have to do something to do with collision volumes when Unreal must be checking to do culling so I found the following method to query that information:

First we have to create a FSceneView from the camera. This code is taken from the UE Answers question.

APlayerCameraManager* Manager = World->GetFirstPlayerController()->PlayerCameraManager;
ULocalPlayer* LocalPlayer = World->GetFirstLocalPlayerFromController();

FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues(
    LocalPlayer->ViewportClient->Viewport,
    World->Scene,
    LocalPlayer->ViewportClient->EngineShowFlags)
    .SetRealtimeUpdate(true));

FVector ViewLocation;
FRotator ViewRotation;
FSceneView* SceneView = LocalPlayer->CalcSceneView(&ViewFamily, /*out*/ ViewLocation, /*out*/ ViewRotation, LocalPlayer->ViewportClient->Viewport);

Once we've created the view we can iterate through all primitive components (includes meshes) and then we can use the bounds from the SceneProxy of the Static Mesh and the bounds of the view to do our own culling.

for (TObjectIterator<UPrimitiveComponent> ScenePrimitsItr; ScenePrimitsItr; ++ScenePrimitsItr)
{
    // Using the Object iterator so we have to skip objects not in the 
    // relevant world
    if (ScenePrimitsItr->GetWorld() == World)
    {
        FPrimitiveSceneProxy* Proxy = ScenePrimitsItr->SceneProxy;
        if (Proxy)
        {
            bool bIsShown = 
                SceneView->ViewFrustum.IntersectSphere(Proxy->GetBounds().Origin, Proxy->GetBounds().SphereRadius)||
                SceneView->ViewFrustum.IntersectBox(Proxy->GetBounds().Origin, Proxy->GetBounds().BoxExtent);
        }
    }
}

The frustrum check came from SceneVisibility.cpp in the method FrustumCull This method isn't ideal as a) involves duplicating that check and b) performing the test twice. However, I couldn't find a way to actually query the result. It appears to be stored in a bit array in the FViewInfo. Unfortunately this info is not exposed outside of the renderer module.

like image 159
T. Kiley Avatar answered Oct 22 '25 04:10

T. Kiley


You could try this to create an array of actors: enter image description here

But I don't know if it's good performance wise if there are too many actors of the class you want.

like image 41
Ghar Avatar answered Oct 22 '25 06:10

Ghar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!