Replicated

[FPSScoring] 총알 본문

언리얼 엔진/Mini Projects [Unreal]

[FPSScoring] 총알

라구넹 2025. 2. 27. 07:34
// h
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "FSBullet.generated.h"

UCLASS()
class FPSSCORING_API AFSBullet : public AActor
{
	GENERATED_BODY()
	
public:	
	AFSBullet();

protected:
	UFUNCTION()
	void OnComponentBeginOverlapCallback(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepHitResult);

	UPROPERTY()
	TObjectPtr<class USphereComponent> Trigger;

	UPROPERTY()
	TObjectPtr<class UStaticMeshComponent> StaticMeshComp;

	UPROPERTY()
	TObjectPtr<class UProjectileMovementComponent> Movement;
};


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


#include "Actor/FSBullet.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "Components/SphereComponent.h"
#include "Components/StaticMeshComponent.h"
#include "Kismet/GameplayStatics.h"
#include "Physics/FSCollision.h"
#include "Subsystem/FSScoreSubsystem.h"
#include "Game/FSGameMode.h"

// Sets default values
AFSBullet::AFSBullet()
{
	Trigger = CreateDefaultSubobject<USphereComponent>(TEXT("Trigger"));
	Trigger->InitSphereRadius(5.0f);
	Trigger->SetCollisionProfileName(CPROFILE_FSTRIGGER);
	RootComponent = Trigger;
	Trigger->OnComponentBeginOverlap.AddDynamic(this, &AFSBullet::OnComponentBeginOverlapCallback);

	StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMeshComp"));

	static ConstructorHelpers::FObjectFinder<UStaticMesh> StaticMeshRef(TEXT("/Script/Engine.StaticMesh'/Game/Mesh/SM_Bullet.SM_Bullet'"));
	
	if (StaticMeshRef.Succeeded())
	{
		StaticMeshComp->SetStaticMesh(StaticMeshRef.Object);
	}

	StaticMeshComp->SetRelativeScale3D(FVector(0.1f, 0.1, 0.1f));
	StaticMeshComp->SetupAttachment(RootComponent);
	StaticMeshComp->SetRelativeLocation(FVector(0.0f, 0.0f, 0.0f));

	Movement = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("Movement"));
	Movement->InitialSpeed = 3000.0f; 
	Movement->MaxSpeed = 3000.0f;     
	Movement->bRotationFollowsVelocity = true;
	Movement->bShouldBounce = false;

	InitialLifeSpan = 3.0f;
}

void AFSBullet::OnComponentBeginOverlapCallback(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepHitResult)
{
	UFSScoreSubsystem* ScoreSubsystem = GetWorld()->GetSubsystem<UFSScoreSubsystem>();
	if (ScoreSubsystem)
	{
		ScoreSubsystem->SetScore(ScoreSubsystem->GetScore() + 1);
		UE_LOG(LogTemp, Log, TEXT("Hit! - %d"), ScoreSubsystem->GetScore());

		AFSGameMode* GameMode = Cast<AFSGameMode>(GetWorld()->GetAuthGameMode());
		GameMode->SetScoreText(FString::FromInt(ScoreSubsystem->GetScore()));
	}

	OtherActor->Destroy();

	Destroy();
}

액터에 UProjectileMovementComponent 달아서 사용

 

void AFSCharacterPlayer::Shoot()
{
	if (bIsShooted) return;
	bIsShooted = true;

	FVector SpawnLocation = GetActorLocation() + GetActorForwardVector() * 100.0f;
	FRotator SpawnRotation = GetControlRotation();

	FActorSpawnParameters SpawnParams;
	SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; 

	AFSBullet* Bullet = GetWorld()->SpawnActor<AFSBullet>(AFSBullet::StaticClass(), SpawnLocation, SpawnRotation, SpawnParams);
}

플레이어가 쏠 때 회전 ControlRotation으로 정해주면 됨