The original tutorial is based on UE 4.18, I am based on UE 4.25]
Following the previous tutorial, this tutorial is very interesting. We will simulate the explosion by adding radial thrust to all objects within the set range.
Create a new role named AddRadialForce. We don't need to do anything with the header file. The following is the default header file generated by illusion.
AddRadialForce.h
#pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "AddRadialForce.generated.h" UCLASS() class UNREALCPP_API AAddRadialForce : public AActor { GENERATED_BODY() public: // Sets default values for this actor's properties AAddRadialForce(); protected: // Called when the game starts or when spawned virtual void BeginPlay() override; public: // Called every frame virtual void Tick(float DeltaTime) override; };
To help during debugging, let's add the DrawDebugHelpers header file to our code.
#include "AddRadialForce.h" // add debug helpfers #include "DrawDebugHelpers.h"
In this example, we will execute all the logic in the BeginPlay() function. We want to collect all hit results in our range and get results from the scan of our range. To do this, we will use TArray to track overlapping actor s.
void AAddRadialForce::BeginPlay() { Super::BeginPlay(); // create tarray for hit results TArray<FHitResult> OutHits; // crate tarray for sweep actors TArray<AActor*> SweepActors; }
Next, we will declare the TArray array OutHits. We want the scanning range to start and end from the position of the actor, and let the CollisionShape be a 500 unit sphere. You can use GetActorLocation() to get the location of the actor, which returns a vector. We use fcollisionshape:: makesphere (500.0f) to create a CollisionShape.
// Called when the game starts or when spawned void AAddRadialForce::BeginPlay() { Super::BeginPlay(); // create tarray for hit results TArray<FHitResult> OutHits; // get actor locations FVector MyLocation = GetActorLocation(); // start and end locations. The sphere will create the radial sweep. FVector Start = MyLocation; FVector End = MyLocation; // create a collision sphere FCollisionShape MyColSphere = FCollisionShape::MakeSphere(500.0f); }
To visualize the scanned sphere, we will draw a debug sphere.
// Called when the game starts or when spawned void AAddRadialForce::BeginPlay() { Super::BeginPlay(); // create tarray for hit results TArray<FHitResult> OutHits; // get actor locations FVector MyLocation = GetActorLocation(); // start and end locations. The sphere will create the radial sweep. FVector Start = MyLocation; FVector End = MyLocation; // create a collision sphere FCollisionShape MyColSphere = FCollisionShape::MakeSphere(500.0f); // draw collision sphere DrawDebugSphere(GetWorld(), GetActorLocation(), MyColSphere.GetSphereRadius(), 50, FColor::Cyan, true); }
Next, we want to check whether our actor hit anything when we BeginPlay(). Each actor has the GetWorld function. From the, we will use the SweepMultiByChannel() function obtained from the GetWorld() function and set the variable just created above as the parameter. This returns a bool indicating whether there are other} actors within the scope of that actor.
void AAddRadialForce::BeginPlay() { Super::BeginPlay(); // create tarray for hit results TArray<FHitResult> OutHits; // get actor locations FVector MyLocation = GetActorLocation(); // start and end locations. The sphere will create the radial sweep. FVector Start = MyLocation; FVector End = MyLocation; // create a collision sphere FCollisionShape MyColSphere = FCollisionShape::MakeSphere(500.0f); // draw collision sphere DrawDebugSphere(GetWorld(), GetActorLocation(), MyColSphere.GetSphereRadius(), 50, FColor::Cyan, true); // check if something got hit in the sweep bool isHit = GetWorld()->SweepMultiByChannel(OutHits, Start, End, FQuat::Identity, ECC_WorldStatic, MyColSphere); }
If isHit is true, we will add radial thrust to the root component of each successful cast actor by traversing the array {OutHits.
if (isHit) { // loop through TArray for (auto& Hit : OutHits) { UStaticMeshComponent* MeshComp = Cast<UStaticMeshComponent>((Hit.GetActor())->GetRootComponent()); if (MeshComp) { // alternivly you can use ERadialImpulseFalloff::RIF_Linear for the impulse to get linearly weaker as it gets further from origin. // set the float radius to 500 and the float strength to 2000. MeshComp->AddRadialImpulse(GetActorLocation(), 500.f, 2000.f, ERadialImpulseFalloff::RIF_Constant, true); } } }
The final complete cpp code is as follows
#include "AddRadialForce.h" // add debug helpfers #include "DrawDebugHelpers.h" // Sets default values AAddRadialForce::AAddRadialForce() { // 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; } // Called when the game starts or when spawned void AAddRadialForce::BeginPlay() { Super::BeginPlay(); // create tarray for hit results TArray<FHitResult> OutHits; // get actor locations FVector MyLocation = GetActorLocation(); // start and end locations. The sphere will create the radial sweep. FVector Start = MyLocation; FVector End = MyLocation; // create a collision sphere FCollisionShape MyColSphere = FCollisionShape::MakeSphere(500.0f); // draw collision sphere DrawDebugSphere(GetWorld(), GetActorLocation(), MyColSphere.GetSphereRadius(), 50, FColor::Cyan, true); // check if something got hit in the sweep bool isHit = GetWorld()->SweepMultiByChannel(OutHits, Start, End, FQuat::Identity, ECC_WorldStatic, MyColSphere); if (isHit) { // loop through TArray for (auto& Hit : OutHits) { UStaticMeshComponent* MeshComp = Cast<UStaticMeshComponent>((Hit.GetActor())->GetRootComponent()); if (MeshComp) { // alternivly you can use ERadialImpulseFalloff::RIF_Linear for the impulse to get linearly weaker as it gets further from origin. // set the float radius to 500 and the float strength to 2000. MeshComp->AddRadialImpulse(GetActorLocation(), 500.f, 2000.f, ERadialImpulseFalloff::RIF_Constant, true); } } } } // Called every frame void AAddRadialForce::Tick(float DeltaTime) { Super::Tick(DeltaTime); }
The effect diagram of actual operation is as follows