Coin pickup counter with UE5 and C++

Hi, Thank you for the advice and help so far!!
For now, my codes do not have any errors. Could you check and make sure if my codes are good enough to start make a counter by blueprint on my UE5?

CoinPickupTutorialCharacter.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "InputActionValue.h"
#include "CoinPickupTutorialCharacter.generated.h"


UCLASS(config=Game)
class ACoinPickupTutorialCharacter : public ACharacter
{
	GENERATED_BODY()

	/** Camera boom positioning the camera behind the character */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
	class USpringArmComponent* CameraBoom;

	/** Follow camera */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
	class UCameraComponent* FollowCamera;
	
	/** MappingContext */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
	class UInputMappingContext* DefaultMappingContext;

	/** Jump Input Action */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
	class UInputAction* JumpAction;

	/** Move Input Action */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
	class UInputAction* MoveAction;

	/** Look Input Action */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
	class UInputAction* LookAction;

	//code I just added(Oct4th)
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = “Counter”)
	uint16 CoinAmount;

public:
	ACoinPickupTutorialCharacter();
	void AddCoinByValue(uint8 Value);

protected:

	/** Called for movement input */
	void Move(const FInputActionValue& Value);

	/** Called for looking input */
	void Look(const FInputActionValue& Value);

	
			

protected:
	// APawn interface
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
	
	// To add mapping context
	virtual void BeginPlay();

public:
	/** Returns CameraBoom subobject **/
	FORCEINLINE class USpringArmComponent* GetCameraBoom() const { return CameraBoom; }
	/** Returns FollowCamera subobject **/
	FORCEINLINE class UCameraComponent* GetFollowCamera() const { return FollowCamera; }
};

CoinPickupTutorialCharacter.cpp

#include "CoinPickupTutorialCharacter.h"
#include "Camera/CameraComponent.h"
#include "Components/CapsuleComponent.h"
#include "Components/InputComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "GameFramework/Controller.h"
#include "GameFramework/SpringArmComponent.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"


//////////////////////////////////////////////////////////////////////////
// ACoinPickupTutorialCharacter

ACoinPickupTutorialCharacter::ACoinPickupTutorialCharacter()
{
	// Set size for collision capsule
	GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f);
		
	// Don't rotate when the controller rotates. Let that just affect the camera.
	bUseControllerRotationPitch = false;
	bUseControllerRotationYaw = false;
	bUseControllerRotationRoll = false;

	// Configure character movement
	GetCharacterMovement()->bOrientRotationToMovement = true; // Character moves in the direction of input...	
	GetCharacterMovement()->RotationRate = FRotator(0.0f, 500.0f, 0.0f); // ...at this rotation rate

	// Note: For faster iteration times these variables, and many more, can be tweaked in the Character Blueprint
	// instead of recompiling to adjust them
	GetCharacterMovement()->JumpZVelocity = 700.f;
	GetCharacterMovement()->AirControl = 0.35f;
	GetCharacterMovement()->MaxWalkSpeed = 500.f;
	GetCharacterMovement()->MinAnalogWalkSpeed = 20.f;
	GetCharacterMovement()->BrakingDecelerationWalking = 2000.f;

	// Create a camera boom (pulls in towards the player if there is a collision)
	CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
	CameraBoom->SetupAttachment(RootComponent);
	CameraBoom->TargetArmLength = 400.0f; // The camera follows at this distance behind the character	
	CameraBoom->bUsePawnControlRotation = true; // Rotate the arm based on the controller

	// Create a follow camera
	FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
	FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName); // Attach the camera to the end of the boom and let the boom adjust to match the controller orientation
	FollowCamera->bUsePawnControlRotation = false; // Camera does not rotate relative to arm

	// Note: The skeletal mesh and anim blueprint references on the Mesh component (inherited from Character) 
	// are set in the derived blueprint asset named ThirdPersonCharacter (to avoid direct content references in C++)
}

void ACoinPickupTutorialCharacter::BeginPlay()
{
	// Call the base class  
	Super::BeginPlay();

	//Add Input Mapping Context
	if (APlayerController* PlayerController = Cast<APlayerController>(Controller))
	{
		if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
		{
			Subsystem->AddMappingContext(DefaultMappingContext, 0);
		}
	}
}

//////////////////////////////////////////////////////////////////////////
// Input

void ACoinPickupTutorialCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
{
	// Set up action bindings
	if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent)) {
		
		//Jumping
		EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Triggered, this, &ACharacter::Jump);
		EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Completed, this, &ACharacter::StopJumping);

		//Moving
		EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &ACoinPickupTutorialCharacter::Move);

		//Looking
		EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &ACoinPickupTutorialCharacter::Look);

	}

}

void ACoinPickupTutorialCharacter::Move(const FInputActionValue& Value)
{
	// input is a Vector2D
	FVector2D MovementVector = Value.Get<FVector2D>();

	if (Controller != nullptr)
	{
		// find out which way is forward
		const FRotator Rotation = Controller->GetControlRotation();
		const FRotator YawRotation(0, Rotation.Yaw, 0);

		// get forward vector
		const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
	
		// get right vector 
		const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);

		// add movement 
		AddMovementInput(ForwardDirection, MovementVector.Y);
		AddMovementInput(RightDirection, MovementVector.X);
	}
}

void ACoinPickupTutorialCharacter::Look(const FInputActionValue& Value)
{
	// input is a Vector2D
	FVector2D LookAxisVector = Value.Get<FVector2D>();

	if (Controller != nullptr)
	{
		// add yaw and pitch input to controller
		AddControllerYawInput(LookAxisVector.X);
		AddControllerPitchInput(LookAxisVector.Y);
	}
}

//i just added code(Oct 4)
void ACoinPickupTutorialCharacter::AddCoinByValue(uint8 Value)
{
	CoinAmount += Value;
}

CPT_CoinPickupActor.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "NiagaraFunctionLibrary.h"
#include "NiagaraComponent.h"
#include "CPT_CoinPickupActor.generated.h"



class UStaticMeshComponent;
class URotatingMovementComponent;
class USphereComponent;
class UNiagaraSystem;
class USoundBase;

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

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

	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Counter")
	uint16 CoinAmount;

	

protected:
	//Constructor

	UPROPERTY(EditDefaultsOnly, Category = "Coin Pickup Tutorial")
	TObjectPtr<UStaticMeshComponent> MeshComponent;

	UPROPERTY(EditDefaultsOnly, Category = "Coin Pickup Tutorial")
	TObjectPtr<URotatingMovementComponent> RotatingMovementComponent;

	UPROPERTY(EditDefaultsOnly, Category = "Coin Pickup Tutorial")
	TObjectPtr<USphereComponent> ColliderComponent;

	UPROPERTY(EditDefaultsOnly, Category = "Coin Pickup Tutorial")
	TObjectPtr<UNiagaraSystem> OnPickupEffect;

	UPROPERTY(EditDefaultsOnly, Category = "Coin Pickup Tutorial")
	TObjectPtr<USoundBase> PickSound;

	UPROPERTY(EditDefaultsOnly, Category = "Coin Pickup Tutorial")
	float VolumeMultiplier{ 0.5 };

	UPROPERTY(EditDefaultsOnly, Category = "Coin Pickup Tutorial")
	float PickEffectSpawnOffset{ 90 };

	virtual void BeginPlay() override;


	
};

CPT_CoinPickupActor.cpp

#include "CPT_CoinPickupActor.h"
#include "CoinPickupTutorial/CoinPickupTutorialCharacter.h"
#include "Components/SphereComponent.h"
#include "GameFramework/Character.h"
#include "GameFramework/RotatingMovementComponent.h"
#include "Kismet/GameplayStatics.h"

#include "NiagaraFunctionLibrary.h"
#include "NiagaraComponent.h"

// Sets default values
ACPT_CoinPickupActor::ACPT_CoinPickupActor()
{
	// 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;

	ColliderComponent = CreateDefaultSubobject<USphereComponent>("ColliderComponent");
	SetRootComponent(ColliderComponent);
	ColliderComponent->SetGenerateOverlapEvents(true);
	ColliderComponent->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
	ColliderComponent->SetCollisionResponseToAllChannels(ECR_Ignore);
	ColliderComponent->SetCollisionResponseToChannel(ECC_Pawn, ECR_Overlap);

	

	MeshComponent = CreateDefaultSubobject<UStaticMeshComponent>("MeshComponent");
	MeshComponent->SetupAttachment(ColliderComponent);
	MeshComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
	MeshComponent->SetCollisionResponseToAllChannels(ECR_Ignore);
	MeshComponent->SetGenerateOverlapEvents(false);

	RotatingMovementComponent = CreateDefaultSubobject<URotatingMovementComponent>("RotatingMovementComponent");


	
}

void ACPT_CoinPickupActor::OnBeginOverlapComponentEvent(
	UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp,
	int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult
)
{
	ACoinPickupTutorialCharacter* Char = Cast<ACoinPickupTutorialCharacter>(OtherActor);
	if (!Char)
	{
		return;
	}

	Char->AddCoinByValue(1);

		if (PickSound)
		{
			UGameplayStatics::PlaySoundAtLocation(
				this, PickSound, GetActorLocation(), VolumeMultiplier);
		}

	if (OnPickupEffect)
	{
		const FVector Offset = GetActorUpVector() * PickEffectSpawnOffset;
		UNiagaraFunctionLibrary::SpawnSystemAtLocation(
			this, OnPickupEffect, OtherActor->GetActorLocation() + Offset);
	}

	Destroy();
}

void ACPT_CoinPickupActor::BeginPlay()
{
	// Call the base class  
	Super::BeginPlay();

	ColliderComponent->OnComponentBeginOverlap.AddDynamic(
		this, &ACPT_CoinPickupActor::OnBeginOverlapComponentEvent
	);
}

CoinPickupTutorial.Build.cs

using System;
using System.IO;
using UnrealBuildTool;

public class CoinPickupTutorial : ModuleRules
{
    public CoinPickupTutorial(ReadOnlyTargetRules Target) : base(Target)
    {
        PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

        PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay", "EnhancedInput" });
        PrivateDependencyModuleNames.AddRange(new string[] { "Niagara" });
    }
}

I think its fine, just test it and check the result

Sounds great. I will ask you again if I have any problems.

Hi, I am working on creating a coin counter on Blueprint, but I have no idea what I should choose here. I think that there should be a category which is like coin counter or something related to coin, but it seems like there is not.
What should I choose, or what should I do here?? I am doing this by following the video

Hi Actually, I just noticed there are a few more errors on CoinPickupTutorialCharacter.cpp


On lines 85 and 114
class “ACoinPickupTutorialCharacter” has no member “Look”

On lines 119 -124
“Controller”, “AddControllerYawInput”, “AddControllerPitchInput” are undefined.

About the widget that doesn’t show the variable, is your BP_ThirdPersonChar type is your custom character class? If it’s not, you have to match the type with your custom character class.

For the second one, you might want to check your header file, make sure the Look function already match the declaration and already defined in the header.

I just solved the second one.
For the widget problem, how can I check if BP_ThirdPersonChar type is my custom character class?

you can check your variable in your Widget blueprint. after you change it, just cast it from your character before in the Widget blueprint

I got confused because I could not find any that like I could change my variable in my widget blueprint.

Go to your widget blueprint graph, you can see your variable there

Should I choose “Coin Pickup Tutorial Character” , or “Coin Pickup Actor” because this is the coin itself ??


if I choose that I get a message below. What should I do there??

Create a blueprint of your C++ Custom created character, and use that instead of BP_ThirdPerson, dont forget to also change your default pawn class to that BP_CustomCharacter from game mode also. Use that BP_CustomChar in widget, and bind the coin with CoinAmount from it.

1 Like

Thank you for helping so far. I have been still working on the project, but I think it is on the right track and the goal is almost there.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.