1
\$\begingroup\$

I've been moving from Unity to Unreal and I'm finding it difficult to grasp the Raycast (Trace) logic of Unreal.

The use case I'm trying to implement at the moment is to trace a ray and check if I hit a specific set of objects or if there are other objects blocking the line of sight.

In Unity, I would use Raycast, define a new specific Layer, set the object layer to it, create a LayerMask with that Layer and Raycast. I consider this method to be performant as the use of layer masks provide a form of optimization and most importantly I'm guaranteed that if the ray hits an object than it's because its layer is part of the layer mask and if I'm using multiple layers I could simply check which layer the hit object has.

In Unreal it's been harder to understand what are the solutions that offer better performance and are easier to use. The C++ documentation for Line Trace (channel or object type) is very poor when comparing to Unity's.

Can anyone shed some light on how to move from the Unity logic to Unreal using the above use case as an example?

\$\endgroup\$
  • \$\begingroup\$ Are you trying to do this in Blueprints or C++? \$\endgroup\$ – Stephen Mar 20 at 14:36
  • \$\begingroup\$ @Stephen With C++, I don't like building core logic with Blueprints. \$\endgroup\$ – Daniel Marques Mar 20 at 14:56
1
\$\begingroup\$

To do this in C++ / Unreal, you need to do the following either in (or called by) EventTick or on a timer:

// Set up parameters for getting the player viewport
    FVector PlayerViewPointLocation;
    FRotator PlayerViewPointRotation;

// Get player viewport and set these parameters
    GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(
    OUT PlayerViewPointLocation, 
    OUT PlayerViewPointRotation
    );

// Parameter for how far out the the line trace reaches
    float Reach = 100.f;
    FVector LineTraceEnd = PlayerViewPointLocation + PlayerViewPointRotation.Vector() * Reach;

// Set parameters to use line tracing
    FHitResult Hit; 
    FCollisionQueryParams TraceParams(FName(TEXT("")), false, GetOwner());  // false to ignore complex collisions and GetOwner() to ignore self

// Raycast out to this distance
    GetWorld()->LineTraceSingleByObjectType(
        OUT Hit,
        PlayerViewPointLocation,
        LineTraceEnd,
        FCollisionObjectQueryParams(ECollisionChannel::ECC_PhysicsBody),
        TraceParams
    );

// See what if anything has been hit and return what
    AActor* ActorHit = Hit.GetActor();

    if (ActorHit) {
        UE_LOG(LogTemp, Error, TEXT("Line trace has hit: %s"), *(ActorHit->GetName()))
    }

This will return the first actor that has been hit. If you want to find a specific actor, you can say:

if (ActorHit == Cast<AYourCustomActorClass>(YourCustomClass))

Which will only return true if the first item hit is the specific class you're looking for.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thank you very much for your answer. Is casting the only way to check if it's the specific actor? Generally casting can be quite taxing, that's why in Unity I would check using the Layer. By the way, isn't the syntax for casting in UE4 Cast<ClassToCast>(myActor)? \$\endgroup\$ – Daniel Marques Mar 20 at 17:13
  • 1
    \$\begingroup\$ @DanielMarques You're correct about the casting. I've edited to show it. To avoid issues with casting and overhead, you can create an AYourCustomActorClass* MyActorReference variable and see if it exists, only casting if it doesn't. As for the layer thing, if I'm correct then if you're using custom collision, Unreal will ignore other things in front of it and only check if it is colliding with a specific collision setting. \$\endgroup\$ – Stephen Mar 21 at 13:20
  • \$\begingroup\$ Great idea on "caching" the cast. I've experimented with custom collision but I do want other objects to block the trace, so the solution you presented is correct for me. \$\endgroup\$ – Daniel Marques Mar 21 at 13:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.