Im trying to make an interaction system for my game and i cant seem to get it work:
#pragma once
include “CoreMinimal.h”
include “GameFramework/Character.h”
include “GameFramework/CharacterMovementComponent.h”
include “PlayerCharacter.generated.h”
class IInteract_Interface; // Forward declaration
class AActor; // Forward declaration
UCLASS()
class FIRSTGAME_API APlayerCharacter : public ACharacter
{
GENERATED_BODY()
public:
// Sets default values for this character’s properties
APlayerCharacter();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
float SprintSpeed = 525.f;
float WalkSpeed = 250.f;
float InteractionRange = 200.f;
float InteractCheckInterval = 0.4f;
FTimerHandle InteractCheckTimer;
private:
IInteract_Interface* CurrentInteractableInterface;
AActor* CurrentInteractableActor;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
protected:
UPROPERTY(EditAnywhere)
class UCameraComponent* Camera; // Creates a camera class (Object) called "Camera"
UPROPERTY(EditAnywhere, Category = "Camera Shake")
TSubclassOf<class UCameraShakeBase> IdleCameraShake;
UPROPERTY(EditAnywhere, Category = "Camera Shake")
TSubclassOf<class UCameraShakeBase> WalkCameraShake;
UPROPERTY(EditAnywhere, Category = "Camera Shake")
TSubclassOf<class UCameraShakeBase> SprintCameraShake;
void UpdateCameraShakeBasedOnSpeed();
void MoveForward(float InputValue);
void MoveRight(float InputValue);
void Turn(float InputValue);
void LookUp(float InputValue);
void StartSprint();
void StopSprint();
void Interact();
void CheckForInteractable();
};
this is my PlayerCharacter.h file
include “FirstGame/Player/PlayerCharacter.h”
include “Camera/CameraComponent.h” // Includes the Camera class created in PlayerCharacter.h
include “Kismet/GameplayStatics.h”
include “FirstGame/Interaction/Interact_Interface.h”
include “DrawDebugHelpers.h”
// Sets default values when unreal engine is opened
APlayerCharacter::APlayerCharacter()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don’t need it.
PrimaryActorTick.bCanEverTick = true;
Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Player Camera")); // Creates a camera called "Player Camera" using the class created in PlayerCharacter.h
Camera->SetupAttachment(RootComponent); // Attaches the camera to the player
Camera->bUsePawnControlRotation = true;
IdleCameraShake = nullptr;
WalkCameraShake = nullptr;
SprintCameraShake = nullptr;
CurrentInteractableInterface = nullptr;
}
// Called when the game starts or when spawned
void APlayerCharacter::BeginPlay()
{
Super::BeginPlay();
GetWorldTimerManager().SetTimer(InteractCheckTimer, this, &APlayerCharacter::CheckForInteractable, InteractCheckInterval, true);
}
// Called every frame
void APlayerCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
UpdateCameraShakeBasedOnSpeed();
}
// Called to bind functionality to input
void APlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
PlayerInputComponent->BindAxis("MoveForward", this, &APlayerCharacter::MoveForward);
PlayerInputComponent->BindAxis("MoveRight", this, &APlayerCharacter::MoveRight);
PlayerInputComponent->BindAxis("Turn", this, &APlayerCharacter::Turn);
PlayerInputComponent->BindAxis("LookUp", this, &APlayerCharacter::LookUp);
PlayerInputComponent->BindAction("Sprint", IE_Pressed, this, &APlayerCharacter::StartSprint);
PlayerInputComponent->BindAction("Sprint", IE_Released, this, &APlayerCharacter::StopSprint);
PlayerInputComponent->BindAction("Interact", IE_Pressed, this, &APlayerCharacter::Interact);
}
void APlayerCharacter::UpdateCameraShakeBasedOnSpeed() // Camera Shake For Player Movement Based On Speed
{
APlayerController* PlayerController = UGameplayStatics::GetPlayerController(this, 0);
FVector CharacterVelocity = GetCharacterMovement()->Velocity;
float CharacterSpeed = CharacterVelocity.Size();
float IdleSpeedThreshold = 100.0f;
float WalkSpeedThreshold = 300.0f;
float SprintSpeedThreshold = 550.f;
TSubclassOf<UCameraShakeBase> CameraShakeToPlay = nullptr;
if (CharacterSpeed < IdleSpeedThreshold)
{
CameraShakeToPlay = IdleCameraShake;
}
else if (CharacterSpeed < WalkSpeedThreshold)
{
CameraShakeToPlay = WalkCameraShake;
}
else if (CharacterSpeed < SprintSpeedThreshold)
{
CameraShakeToPlay = SprintCameraShake;
}
if (PlayerController && CameraShakeToPlay)
{
PlayerController->ClientStartCameraShake(CameraShakeToPlay);
}
}
void APlayerCharacter::MoveForward(float InputValue) // Defines what the MoveForward function created in PlayerCharacter.h does
{
FVector ForwardDirection = GetActorForwardVector(); // Gets direction player is facing
AddMovementInput(ForwardDirection, InputValue); // Adds movement input forward / backward
}
void APlayerCharacter::MoveRight(float InputValue) // Defines what the MoveRight function created in PlayerCharcter.h does
{
FVector RightDirection = GetActorRightVector(); // Gets direction of players right side
AddMovementInput(RightDirection, InputValue); // Adds movement input right / left
}
void APlayerCharacter::Turn(float InputValue) // Defines what the Turn Function created in PlayerCharacter.h does
{
AddControllerYawInput(InputValue); // Turns Camera
}
void APlayerCharacter::LookUp(float InputValue) // Defines what the LookUp function created in PlayerCharacter.h does
{
AddControllerPitchInput(InputValue); // Turns Camera
}
void APlayerCharacter::StartSprint() // Starts Sprint
{
UCharacterMovementComponent* PlayerCharacterMovement = GetCharacterMovement();
if (PlayerCharacterMovement) {
PlayerCharacterMovement->MaxWalkSpeed = SprintSpeed;
}
}
void APlayerCharacter::StopSprint() // Stops Sprint
{
UCharacterMovementComponent* PlayerCharacterMovement = GetCharacterMovement();
if (PlayerCharacterMovement) {
PlayerCharacterMovement->MaxWalkSpeed = WalkSpeed;
}
}
void APlayerCharacter::Interact() // Interacts
{
if (CurrentInteractableInterface)
{
UE_LOG(LogTemp, Warning, TEXT(“INTERACT - CurrentInteractableInterface is valid”));
IInteract_Interface* Interactable = Cast<IInteract_Interface>(CurrentInteractableActor);
if (Interactable)
{
UE_LOG(LogTemp, Warning, TEXT(“INTERACT - CurrentInteractableActor is valid”));
// Call the Interact function on the interactable item
Interactable->Interact(this);
}
else
{
UE_LOG(LogTemp, Warning, TEXT(“INTERACT - CurrentInteractableActor is NOT valid”));
}
}
else
{
UE_LOG(LogTemp, Warning, TEXT(“INTERACT - CurrentInteractableInterface is NOT valid”));
}
}
void APlayerCharacter::CheckForInteractable()
{
FVector Start = Camera->GetComponentLocation();
FVector ForwardVector = Camera->GetForwardVector();
FVector End = Start + (ForwardVector * InteractionRange);
FHitResult HitResult;
FCollisionQueryParams TraceParams(FName(TEXT("InteractTrace")), false, this);
// Check if the previously interacted object is still in focus, and hide its prompt if not
if (CurrentInteractableActor)
{
UE_LOG(LogTemp, Warning, TEXT("CURRENTINTERACTABLE"));
IInteract_Interface* Interactable = Cast<IInteract_Interface>(CurrentInteractableActor);
if (Interactable)
{
Interactable->HideInteractionPrompt();
UE_LOG(LogTemp, Warning, TEXT("HIDEPROMPT"));
}
CurrentInteractableActor = nullptr;
}
if (GetWorld()->LineTraceSingleByChannel(HitResult, Start, End, ECC_Visibility, TraceParams))
{
// Check if the hit actor implements the InteractableInterface
AActor* HitActor = HitResult.GetActor();
UE_LOG(LogTemp, Warning, TEXT("Hit Actor: %s"), *HitActor->GetName());
UE_LOG(LogTemp, Warning, TEXT("Hit Location: %s"), *HitResult.ImpactPoint.ToString());
IInteract_Interface* Interactable = Cast<IInteract_Interface>(HitActor);
if (Interactable)
{
// Display interaction prompt
Interactable->ShowInteractionPrompt();
CurrentInteractableActor = HitActor; // Update the current interactable object
UE_LOG(LogTemp, Warning, TEXT("SHOWPROMPT"));
}
}
}
this is my PlayerCharacter.cpp file where most of the system is taking place
#pragma once
include “CoreMinimal.h”
include “UObject/Interface.h”
include “Interact_Interface.generated.h”
class APlayerCharacter; // Forward declaration
// This class does not need to be modified.
UINTERFACE(MinimalAPI)
class UInteract_Interface : public UInterface
{
GENERATED_BODY()
};
/**
- Interface for interactable objects.
*/
class FIRSTGAME_API IInteract_Interface
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = “Interaction”)
void ShowInteractionPrompt();
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Interaction")
void Interact(APlayerCharacter* PlayerCharacter);
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Interaction")
void HideInteractionPrompt();
};
and this is my Interact_Interface.h file
the Interact_Interface.cpp file only contains a header to the .h file
at the moment i can add the interface to actors and use the 3 functions i created in blueprints Showprompt, hideprompt, and interact. But none of the functions run and i dont think the system is actually detecting the interface but i could be wrong.
If anyone knows where i went wrong please let me know it would be a life saver!