[UE/Implement] 총기 격발 및 재장전 시스템 구현 (C++ & 블루프린트)

2025. 2. 20. 23:53·Unrael

1. 개요

이번 포스팅에서는

총기 격발 및 재장전 기능을 구현해 보았습니다.

C++와 블루프린트를 함께 사용하여 유연한 시스템을 구성했습니다.

 

2. 기능 요구 사항

  • 좌클릭 시 총알 발사
  • 탄창 수 관리 (예: 20발)
  • 탄환이 0일 때 발사 불가
  • 연사/단발 모드 기능

 

3. 구현 과정

3.1 총기 클래스 헤더 파일

#pragma once

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

UENUM(BlueprintType)
enum class EFireMode : uint8
{
	FullAuto, // 연사
	SemiAuto, // 단발
};

UCLASS()
class SPLATOON_API ABaseGun : public AActor
{
	GENERATED_BODY()

public:	
	ABaseGun();

protected:
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Gun")
	TObjectPtr<USceneComponent> RootComp;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Gun")
	TObjectPtr<USceneComponent> FrontOfGun;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Gun")
	TObjectPtr<UStaticMeshComponent> StaticMeshComp;

	virtual void BeginPlay() override;

/* Fire */
public:
	// 플레이어 격발시 호출
	UFUNCTION(BlueprintCallable)
	void FirePressed();
	// 플레이어 격발 중지시 호출
	UFUNCTION(BlueprintCallable)
	void FireReleased();

protected:
	// 탄환이 격발되는 시간 간격
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category= "Gun|Fire")
	float FireBulletInterval;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category= "Gun|Fire")
	EFireMode FireMode;

	FTimerHandle FireTimerHandle;

	void Fire();

/* Reload */
public:
	// 재장전 시작시 호출
	UFUNCTION(BlueprintCallable)
	void ReloadStart();
	// 재장전 종료
	UFUNCTION(BlueprintCallable)
	void ReloadStop();

protected:
	// 탄환이 장전되는 시간 간격
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category= "Gun|Reload")
	float ReloadBulletInterval;

	FTimerHandle ReloadTimerHandle;

	void Reload();

/* Bullets */
protected:
	// TODO: AActor -> BaseBullet
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gun|Bullets")
	TSubclassOf<AActor> BulletClass;

	// 남은 탄환 수
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gun|Bullets")
	int32 RemainingBullets;

	// 최대 탄환 수
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gun|Bullets")
	int32 MaxRemainingBullets;
};

 

 

3.2 격발 기능

#include "BaseGun.h"
#include "Kismet/GameplayStatics.h"

void ABaseGun::FirePressed()
{
	Fire();
}

void ABaseGun::FireReleased()
{
	if (UWorld* World = GetWorld())
	{
		World->GetTimerManager().ClearTimer(FireTimerHandle);
	}
}

void ABaseGun::Fire()
{
	// 1. 남은 탄환 확인
	if (RemainingBullets <= 0) return;

	// 2. 탄환 감소
	RemainingBullets -= 1;

	// 3. 탄환 생성
	if (UWorld* World = GetWorld())
	{
		World->SpawnActor<AActor>(
			BulletClass,
			FrontOfGun->GetComponentLocation(),
			FrontOfGun->GetComponentRotation()
		);
	}

	// 4. 연사 모드일 경우 타이머 설정
	if (FireMode == EFireMode::FullAuto)
	{
		if (UWorld* World = GetWorld())
		{
			World->GetTimerManager().SetTimer
			(
				FireTimerHandle,
				this,
				&ABaseGun::Fire,
				FireBulletInterval
			);
		}
	}

	GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Fire / RemainingBullets = %d"), RemainingBullets));
}

 

3.3 재장전 기능

void ABaseGun::ReloadStart()
{
	if (UWorld* World = GetWorld())
	{
		// 한 발씩 지속적으로 장전
		World->GetTimerManager().SetTimer(
			ReloadTimerHandle,
			this,
			&ABaseGun::Reload,
			ReloadBulletInterval,
			true
		);
	}
}

void ABaseGun::ReloadStop()
{
	if (UWorld* World = GetWorld())
	{
		World->GetTimerManager().ClearTimer(ReloadTimerHandle);
	}
}	

void ABaseGun::Reload()
{
	if (RemainingBullets >= MaxRemainingBullets) return;

	RemainingBullets += 1;

	GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Reload / RemainingBullets = %d"), RemainingBullets));
}

 

4. 블루프린트 추가 작업

  • 무기별 총알 생성 위치 수정

 

5. 테스트

5.1 격발 기능

좌클릭 시 연사 시작

좌클릭 뗄 경우 연사 종료

5.2  재장전 기능

특정 키 입력시 지속적으로 재장전 시작

특정 키 뗄 경우 재장전 종료

 

✅ 기대 결과:

  • 연사 시작 및 중지
  • 재장전 시작 및 중지
  • 탄환 0일 때 격발 중지
  • 원하는 위치에서 탄환 생성

 

⚠️ 발견된 이슈:

  • 버그: 빠르게 연타 시 재장전 딜레이 무시 → bCanFire 변수를 통한 조건 추가로 해결
  • 개선점: 피격 대상에 데미지 적용 시스템 추가 예정

 

6. 마무리 및 개선 아이디어

  • 무기 사운드 추가
  • 사격 이펙트 추가

GitHub에서 코드 확인 👉 [🔗 GitHub 링크]

 

'Unrael' 카테고리의 다른 글

[Animation] 웅크려 이동하기 (Crouching)  (0) 2025.04.22
[UE] 게임플레이 태그 (GameplayTag)  (0) 2025.03.17
[UE/Settings] 언리얼 에디터 기본 설정  (0) 2025.02.19
[UE/Tools] 스태틱 메시를 스켈레탈 메시로  (1) 2025.02.18
[UE/Project] 기능 명세서 작성  (0) 2025.02.17
'Unrael' 카테고리의 다른 글
  • [Animation] 웅크려 이동하기 (Crouching)
  • [UE] 게임플레이 태그 (GameplayTag)
  • [UE/Settings] 언리얼 에디터 기본 설정
  • [UE/Tools] 스태틱 메시를 스켈레탈 메시로
DevColIn
DevColIn
복잡함을 단순하게
  • DevColIn
    심플한 코딩생활
    복잡함을 단순하게
  • 전체
    오늘
    어제
    • 전체보기 (223)
      • Unreal 부트캠프 (49)
        • TIL (34)
        • 사전캠프 (7)
        • 본캠프 (8)
      • Unrael (10)
        • 환경설정 (0)
        • Basic (19)
        • Component (5)
        • GAS (GameplayAbilitySystem) (3)
        • AI (2)
        • Implement (10)
        • UI (1)
        • Error (1)
        • Network (2)
        • Tip (1)
      • Level Design (5)
      • Math (1)
      • Design Pattern (16)
      • Computer Science (2)
        • Network (1)
        • Database (1)
      • Algorithm (79)
        • Basic (4)
        • Practice (74)
      • C++ (4)
        • Basic (4)
      • Tool (0)
      • Game (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 미디어로그
    • 위치로그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Algorithm
    소프트 레퍼런신
    tsoftobjectptr
    디자인패턴
    assetmanager
    gas
    내일배움캠프
    actor
    퀘스트
    Design Pattern
    Implement
    GameplayEffect
    레벨디자인
    디자인 패턴
    unrealengine
    basic
    게임동기화
    DesignPattern
    사전캠프
    component
    액터
    AI
    KPT회고
    c++
    하드 레퍼런싱
    알고리즘
    unreal
    본캠프
    Til
    Animation
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
DevColIn
[UE/Implement] 총기 격발 및 재장전 시스템 구현 (C++ & 블루프린트)
상단으로

티스토리툴바