Pushing a character inside a triggerbox

Hey Answerhub,

I’m trying to implement a way to constantly push a character that walks into a triggerbox, in one direction.

So far I’ve tried changing the character’s velocity once they step inside the box by using the character movement component, but when I try stepping into the trigger in a test map, my entire PC crashes.

Any ideas on what I can fix or what else I can do to implement the same effect?

void AWindBlowTriggerBox::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	//True on trigger overlap and false on end overlap
	while(bIsTriggered)
	{
		//Apply windstrength vector force if player pointer exists
		if (Player)
		{
			ApplyForce(WindStrength);
		}
	}
}

void AWindBlowTriggerBox::ApplyForce(FVector Force)
{
	//If character cast succeeds, apply the force
	ACharacter* Character = Cast<ACharacter>(Player);
	if (Character) {
		Character->GetCharacterMovement()->Velocity += Force;
		GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Blue, TEXT("Force Applied!"));
	}
}

Hey Mookiez,

Your issue comes from the following:

while( bIsTriggered )

What will happen here is that as soon as your Character overlaps the trigger and bIsTriggered is set to true, Tick() will forever sit in the while loop, preventing the rest of the main game loop from continuing, which freezes your game.

Here is an example of how to have a force volume:

[.h]

#pragma once

#include "GameFramework/Actor.h"
#include "Runtime/Engine/Classes/Components/ArrowComponent.h"
#include "ForceVolume.generated.h"

UCLASS()
class AH489423_API AForceVolume : public AActor
{
	GENERATED_BODY()
    
public:    
    AForceVolume( );
    virtual void Tick( float DeltaTime ) override;
		
    UPROPERTY( BlueprintReadOnly, VisibleAnywhere, Category = "Direction" )
    UArrowComponent *Arrow;
    
    UPROPERTY( BlueprintReadOnly, VisibleAnywhere, Category = "Collision" )
    UBoxComponent *Collider;
    
    UPROPERTY( BlueprintReadOnly, EditAnywhere, Category = "Collision" )
    float ForceAmount;

    UFUNCTION( )
    void Overlap( UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult &SweepResult );

    UFUNCTION( )
    void EndOverlap( UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex );
    
private:
    
    /** This will need to be an TArray<ACharacter*> of characters if a Multiplayer game 
    and Overlap( ) would use .Add( ) and EndOverlap( ) would user .Remove( ) to add or remove touching  
    characters.
    */
    ACharacter *OverlappingCharacter;
};

[.cpp]

#include "AH489423.h"
#include "ForceVolume.h"

AForceVolume::AForceVolume( )
{
     PrimaryActorTick.bCanEverTick = true;
    
    Collider = CreateDefaultSubobject<UBoxComponent>( TEXT("Collider") );
    Collider->OnComponentBeginOverlap.AddDynamic( this, &AForceVolume::Overlap );
    Collider->OnComponentEndOverlap.AddDynamic( this, &AForceVolume::EndOverlap );                                     
    SetRootComponent( Collider );
    
    Arrow = CreateDefaultSubobject<UArrowComponent>( TEXT("Direction Arrow") );
    Arrow->SetupAttachment(  );
    
    ForceAmount = 550000.f;
}

void AForceVolume::Tick( float DeltaTime )
{
    if( OverlappingCharacter && Arrow )
    {
        FVector Direction = Arrow->GetForwardVector( );
        FVector NewVelocity = Direction.GetSafeNormal( ) * ForceAmount;
        NewVelocity.Z = 0.f;
        
        OverlappingCharacter->GetCharacterMovement( )->AddForce( NewVelocity );
    }
    Super::Tick( DeltaTime );
}

void AForceVolume::Overlap( UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult &SweepResult )
{
    ACharacter *Overlapping = Cast<ACharacter>( OtherActor );
    if( Overlapping )
    {
        OverlappingCharacter = Overlapping;
    }
}
    
void AForceVolume::EndOverlap( UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex )
{
    if( OtherActor == OverlappingCharacter )
    {
        OverlappingCharacter = nullptr;
    }
}

Thanks! Much appreciated