The original tutorial is based on UE 4.18, I am based on UE 4.25.

English original Address

To continue the tutorial, create a new actor. In this case, we’ll call our new actor subclass ActorLineTrace.

We don’t need to do anything in the header file. Just in case, here is the header file created by default.

ActorLineTrace.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "ActorLineTrace.generated.h"

UCLASS(a)class UNREALCPP_API AActorLineTrace : public AActor
{
	GENERATED_BODY(a)public:	
	// Sets default values for this actor's properties
	AActorLineTrace(a);protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay(a) override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;
};
Copy the code

To help us visualize the line path, we’ll include the DrawDebugHelpers header file. This will allow us to draw a highlighted line trace. We’ll also include Constructorhelpers.h to immediately add a grid to the actor for visual representation. Adding a grid to the editor is usually preferred (without the help of constructorhelpers.h), but we should continue to try new things in c++.

#include "ActorLineTrace.h"
// add these scripts to use their functions
#include "ConstructorHelpers.h"
#include "DrawDebugHelpers.h"
Copy the code

We add a cube to the actor by creating DefaultSubobject for the UStaticMeshComponent. We then make the new cube the root component of the actor. We programmatically add a grid to the actor by calling FObjectFinder from the ConstructorHelpers. In FObjectFinder, we provide a path to the grid. At this point we need to check if we succeeded in getting the grid. If we successfully get the mesh, we set the StaticMesh, RelativeLocation, and Scale for the actor.

Here’s the code we put into the actor constructor.

AActorLineTrace::AActorLineTrace()
{
 	// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	// add cube to root
    UStaticMeshComponent* Cube = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("VisualRepresentation"));
    Cube->SetupAttachment(RootComponent);

    static ConstructorHelpers::FObjectFinder<UStaticMesh> CubeAsset(TEXT("/Game/StarterContent/Shapes/Shape_Cube.Shape_Cube"));

	if (CubeAsset.Succeeded())
    {
        Cube->SetStaticMesh(CubeAsset.Object);
        Cube->SetRelativeLocation(FVector(0.0 f.0.0 f.0.0 f));
        Cube->SetWorldScale3D(FVector(1.f));
	}
	
	// add another component in the editor to the actor to overlap with the line trace to get the event to fire

}
Copy the code

Next, on the Actor Tick function, we want to trace the line to see if it touches anything.

For this example, we’ll check to see if there are other objects in the same actor. Let’s first create the HitResult and StartingPosition variables, respectively

void AActorLineTrace::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	FHitResult OutHit;
	FVector Start = GetActorLocation(a); }Copy the code

The starting position is a vector, which means it has X,Y, and Z components. I want to move the line up closer to the center of the grid, but at the same time keep it away from the grid so it doesn’t collide with itself. So change the code above to

void AActorLineTrace::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	FHitResult OutHit;
	FVector Start = GetActorLocation(a); Start.Z +=50.f;
	Start.X += 200.f;

}
Copy the code

After that, let’s get the forward vector of the grid by using GetActorForwardVector() to make sure the line tracks move out from the front of the grid. We will then create the End variable to tell the line track where to End. In this example, the row trace will start above 50 units, the first 200 units, and end at the starting point of 500 units.

We also create collision parameter variables for the line trace function.

void AActorLineTrace::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	FHitResult OutHit;
	FVector Start = GetActorLocation(a); Start.Z +=50.f;
	Start.X += 200.f;

	FVector ForwardVector = GetActorForwardVector(a); FVector End = ((ForwardVector *500.f) + Start);
	FCollisionQueryParams CollisionParams;

}
Copy the code

At development time, we want to see our line trajectories. With the above variable, we will use the DrawDebugLine function to draw a green line. If the line trace touches any component in our actor, a message is printed to the screen.

void AActorLineTrace::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	FHitResult OutHit;
	FVector Start = GetActorLocation(a); Start.Z +=50.f;
	Start.X += 200.f;

	FVector ForwardVector = GetActorForwardVector(a); FVector End = ((ForwardVector *500.f) + Start);
	FCollisionQueryParams CollisionParams;

	DrawDebugLine(GetWorld(), Start, End, FColor::Green, false.1.0.5);

	if(ActorLineTraceSingle(OutHit, Start, End, ECC_WorldStatic, CollisionParams))
	{
		GEngine->AddOnScreenDebugMessage(- 1.1.f, FColor::Green, FString::Printf(TEXT("The Component Being Hit is: %s"), *OutHit.GetComponent() - >GetName())); }}Copy the code

Here is the complete CPP code

#include "ActorLineTrace.h"
#include "UObject/ConstructorHelpers.h"
#include "DrawDebugHelpers.h"

// Sets default values
AActorLineTrace::AActorLineTrace()
{
 	// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	// add cube to root
    UStaticMeshComponent* Cube = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("VisualRepresentation"));
    Cube->SetupAttachment(RootComponent);

    static ConstructorHelpers::FObjectFinder<UStaticMesh> CubeAsset(TEXT("/Game/StarterContent/Shapes/Shape_Cube.Shape_Cube"));

	if (CubeAsset.Succeeded())
    {
        Cube->SetStaticMesh(CubeAsset.Object);
        Cube->SetRelativeLocation(FVector(0.0 f.0.0 f.0.0 f)); ///< adjust according to your actual situation
        Cube->SetWorldScale3D(FVector(1.f));
	}
	
	// add another component in the editor to the actor to overlap with the line trace to get the event to fire

}

// Called when the game starts or when spawned
void AActorLineTrace::BeginPlay(a)
{
	Super::BeginPlay(a); }// Called every frame
void AActorLineTrace::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	FHitResult OutHit;
	FVector Start = GetActorLocation(a); Start.Z +=50.f;
	Start.X += 200.f; ///< adjust according to your actual situation

	FVector ForwardVector = GetActorForwardVector(a); FVector End = ((ForwardVector *500.f) + Start);
	FCollisionQueryParams CollisionParams;

	DrawDebugLine(GetWorld(), Start, End, FColor::Green, false.1.0.5);

	if(ActorLineTraceSingle(OutHit, Start, End, ECC_WorldStatic, CollisionParams))
	{
		GEngine->AddOnScreenDebugMessage(- 1.1.f, FColor::Green, FString::Printf(TEXT("The Component Being Hit is: %s"), *OutHit.GetComponent() - >GetName())); }}Copy the code

The actual results are as follows