C++ Collision detection not triggering

I’m having trouble with collision detection in C++. I’ve literally spent hours trying to get it to work and still nothing (I’ve reviewed multiple tutorials and questions to no avail). I’ve tried actor and component based, hit and overlap.

The code compiles and runs, but does nothing when collisions occur.

I have the C++ side scroller template project and I’m trying to create a powerup class, which requires collision detection with the player (I’m trying collision with anything atm).

I’ve got “Simulation generates hit events” and “Generate overlap events” ticked for the sphere collision component, the sphere mesh component, the cube and the player’s capsule collider.

PowerUp.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "GameFramework/Actor.h"
#include "Engine.h"
#include "PowerUp.generated.h"


UCLASS()
class SIDESCROLLER_API APowerUp : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	APowerUp();

	// Called when the game starts or when spawned
	virtual void BeginPlay() override;
	
	// Called when this is hit
	virtual void OnPowerUpHit(AActor *SelfActor, UPrimitiveComponent *OtherActor, FVector NormalImpulse, const FHitResult& Hit);
	virtual void OnPowerUpHitActor(AActor *SelfActor, AActor *OtherActor, FVector NormalImpulse, const FHitResult& Hit);

	virtual void OnOverlapBegin(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

	// Called every frame
	virtual void Tick( float DeltaSeconds ) override;

	//collision primitive to use as root component
	UPROPERTY(EditAnywhere, Category = Pickup)
	USphereComponent *BaseCollisionComponent;

	//static mesh to represent the pickup in game
	UPROPERTY(EditInstanceOnly,  BlueprintReadOnly, Category = Pickup)
	UStaticMeshComponent *PickupMesh;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Pickup)
		bool bIsActive;
	
};

PowerUp.cpp

#include "SideScroller.h"
#include "PowerUp.h"

// Sets default values
APowerUp::APowerUp()
{
	GEngine->AddOnScreenDebugMessage(-1, 5, FColor::Yellow, TEXT("test"));
	if (BaseCollisionComponent != nullptr){
		BaseCollisionComponent->OnComponentHit.AddDynamic(this, &APowerUp::OnPowerUpHit);
		BaseCollisionComponent->OnComponentBeginOverlap.AddDynamic(this, &APowerUp::OnOverlapBegin);
	}
	OnActorHit.AddDynamic(this, &APowerUp::OnPowerUpHitActor);
	SetActorEnableCollision(true);
 	// 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;

}

void APowerUp::OnPowerUpHitActor(AActor *SelfActor, AActor *OtherActor, FVector NormalImpulse, const FHitResult& Hit){
	GEngine->AddOnScreenDebugMessage(-1, 5, FColor::Yellow, TEXT("actor hit!"));

}

// Called when the game starts or when spawned
void APowerUp::BeginPlay()
{
	Super::BeginPlay();
	
}
	
void APowerUp::OnPowerUpHit(AActor *SelfActor, UPrimitiveComponent *OtherActor, FVector NormalImpulse, const FHitResult& Hit){
	GEngine->AddOnScreenDebugMessage(-1, 5, FColor::Yellow, TEXT("touch !"));
}

void APowerUp::OnOverlapBegin(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult){
	GEngine->AddOnScreenDebugMessage(-1, 5, FColor::Yellow, TEXT("overlap !"));
}

// Called every frame
void APowerUp::Tick( float DeltaTime )
{
	Super::Tick( DeltaTime );

}

Put UFUNCTION() above your Collision Function Prototypes

Thanks, I’ve only just seen this, I’ll try it tomorrow.

You haven’t created your components anywhere. Maybe you are doing it in blueprint (?), but anyway they will be null in your constructor, so your test will fail and you won’t add the delegates.

I haven’t read on documentation relating to this, but from personal experience I think it’s better to register delegates later on in an object’s initialization anyway - either PostInitComponents or BeginPlay.

The components are created in the blueprint. I’ll try moving the delegates to PostInitComponents tonight (along with CHADALAK1’s suggestion)

For me having my binding function in begin play fixed the issue

GetCapsuleComponent()->OnComponentBeginOverlap.AddDynamic(this, &ATheTowerCharacter::OnOverlapBegin);

What was the solution to this?

Can confirm that putting UFUNCTION() above the callback functions solved it for me.

In my case, I’m trying to add it on a SplineMeshCompoenent.

In my header I have:

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

in the Cpp I have

SplineMeshComponent->OnComponentBeginOverlap.AddDynamic(this, &ACustomSplineSpawner::OnOverlapBegin);

and the declared method is :

void ACustomSplineSpawner::OnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	UE_LOG(LogTemp, Warning, TEXT("OnOverlapBegin"));
}

and I never see the log apreaing… :frowning:

Since the SplineMeshComponent is created dynamically, do I have anything special to configure for the collision to be triggered ?

You need to call

BaseCollisionComponent->SetGenerateOverlapEvents(true);

in your CDO