Collisions and Pickup in C++ ?

Hello,

Apparently, this is very well documented for blueprints, but I can’t find information about it in C++ (Have you ever (again and again) had this feeling? :frowning: )

This is supposed to be simple: A simple item (e.g. health pack) that can be picked up by the player. To add some small challenge to it, be “pick up-able” only by a friendly teammate (aka: have a simple check function - that won’t cause trouble if the touching actor isn’t able to pick it up).

Ideally, this wouldn’t touch the “blueprint realm”, doing it entirely in C++, but… I guess if there’s no other way, I’ll be happy with a minimalist blueprint approach. >.<

Can you guys give me some advice on the subject? (Or at least point me towards the correct direction? :slight_smile: )

Thank you in advance! :smiley:

1 Like

Create AMyPickup class derived from AActor, set up the mesh and function OnPickedUp. Add sphere component to your character, it will overlap with nearby items. Then on button press (i assume u have button to collect nearby pickup) use GetOverlappingActors and cast it to AMyPickup, if cast is successful call OnPickedUp

That should do

Thanks for your input Pancakez!
Sadly, that does not resolve my issue :frowning:

I can trace or trigger functions using a key press (and, I wasn’t aware of GetOverlappingActors, thanks for that!), so picking up an item with a raytrace is fairly easy for me.

What I’m not able to do is detect a collision and pick a power up based on that (think as health packs in Doom, Quake, Unreal Tournaments, etc.).
I’m surprised at this because it was really simple in Source Engine, yet I’m struggling hard in UE4.

Here’s a basic code:

Header


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

#pragma once

#include "GameFramework/Actor.h"
#include "MyPickup.generated.h"

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

	UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Category = Pickup)
		UCapsuleComponent* BaseCollisionComponent;

	/** StaticMeshComponent to represent the pickup in the level */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Pickup)
		UStaticMeshComponent* PickupMesh;

	/** Function to call when the Pickup is collected. */
	UFUNCTION(BlueprintNativeEvent)
		void OnPickedUp();

	virtual void OnPickedUp_Implementation();

	/** Called when the game starts or when spawned */
	virtual void BeginPlay() override;
	
};


cpp file


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

#include "My.h"
#include "MyPickup.h"


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

	// Create the root CapsuleComponent to handle the pickup's collision
	BaseCollisionComponent = CreateDefaultSubobject<UCapsuleComponent>(TEXT("BaseCapsuleComponent"));

	// Set the SphereComponent as the root component.
	RootComponent = BaseCollisionComponent;

	//Create the static mesh component 
	PickupMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("PickupMesh"));

	// Start with physics simulation disabled, for easy manipulation on UE4 Editor.
	PickupMesh->SetSimulatePhysics(false);

	// Attach the StaticMeshComponent to the RootComponent.
	PickupMesh->AttachTo(RootComponent);
}

// Called when the game starts or when spawned
void AMyPickup::BeginPlay()
{
	Super::BeginPlay();
	UE_LOG(MyCriticalErrors, Warning, TEXT("Spawning Power Up."));
}

void AMyPickup::OnPickedUp_Implementation()
{
	UE_LOG(MyCriticalErrors, Warning, TEXT("Picked up."));
}

So, I’m not been able to find a way to make AMyPickup::OnPickedUp_Implementation() run.
I’m resistant to use BlueprintNativeEvent, because apparently I need to do it in blueprint editor (****, I really would love to setup this entirely in C++ code!)

So, any advice on how to make that run when a player touches the pickupable item ?
Also, it seems there’s no parameter in AMyPickup::OnPickedUp_Implementation(), so, I would have no idea how to get the colliding player when that run.

Thank you again :slight_smile:

Use OnComponentBeginOverlap() for your collision sphere and it fires when you collide with the pickup.

Thank you @Pancakez and @anonymous_user_9fbef36c!

I managed to get it working thanks to your directions! :smiley:

Here’s the code, if someone in future struggle with this too:

Header

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

#pragma once

#include "GameFramework/Actor.h"
#include "MyPickup.generated.h"

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

	UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Category = Pickup)
		UCapsuleComponent* BaseCollisionComponent;

	/** StaticMeshComponent to represent the pickup in the level */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Pickup)
		UStaticMeshComponent* PickupMesh;

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

};

CPP File:

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

#include "My.h"
#include "MyPickup.h"


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

	// Create the root CapsuleComponent to handle the pickup's collision
	BaseCollisionComponent = CreateDefaultSubobject<UCapsuleComponent>(TEXT("BaseCapsuleComponent"));

	// Set the SphereComponent as the root component.
	RootComponent = BaseCollisionComponent;

	//Create the static mesh component 
	PickupMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("PickupMesh"));

	// Start with physics simulation disabled, for easy manipulation on UE4 Editor.
	PickupMesh->SetSimulatePhysics(false);

	// Attach the StaticMeshComponent to the RootComponent.
	PickupMesh->AttachTo(RootComponent);

	// Enable the generation of overlapping events and assign a function to be run when it happens.
	BaseCollisionComponent->bGenerateOverlapEvents = true;
	BaseCollisionComponent->OnComponentBeginOverlap.AddDynamic(this, &AMyPickup::OnOverlapBegin);

	// Disable Overlap Events on the Mesh
	PickupMesh->bGenerateOverlapEvents = false;
}

void AMyPickup::OnOverlapBegin(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	// OtherActor is the actor that triggered the event. Check that is not ourself
	if ( (OtherActor == nullptr) || (OtherActor == this) || (OtherComp == nullptr) )
		return;

	UE_LOG(MyCriticalErrors, Warning, TEXT("Picked up."));
}

Just create the pickup-able item blueprint, enable bGenerateOverlapEvents on the character collision mesh and enjoy!

Hope it helps someone out there! :slight_smile:

I tried what you said and it worked. Thank you very much for posting the final result.

I tried similar things with collision. For some reason I cannot get the “character” to collide with an object and use “OnHit”.

The only change required is the function signature. Your post is from 2015 so that is expected. Here is what worked for me:



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


I am trying to create a coin collection system . I tried above code but nothing happens .Character just hit the coin but there is no log .

in coinpickup.h


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


in coinpickup.cpp


void ACoinPickup::OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
// Other Actor is the actor that triggered the event. Check that is not ourself.
if ((OtherActor != nullptr) && (OtherActor != this) && (OtherComp != nullptr))
{
// Log events
UE_LOG(LogTemp, Warning, TEXT("Picked up."));
}
}

i have set bGenerateOverlapEvents on both character( unreal default character ) and my coin pickup . I have also set Collision preset in my pickup to CharacterMesh