[C++ 기초 5편] C++와 블루프린트로 게임 만들기

김여울·2025년 5월 16일

사전캠프

목록 보기
24/24

🔑 Visual Studio 코드 탐색 단축키

단축키설명
Ctrl + 클릭함수, 클래스, 변수 이름 위에 마우스를 올리고 Ctrl을 누른 채 클릭하면, 해당 항목이 정의된 위치(헤더 파일 또는 소스 파일)로 이동
Alt + F12 (Peek Definition)전체 파일로 이동하지 않고, 하단에 미리보기 창을 열어 정의 내용을 확인 가능
F12 (Go to Definition)선택한 항목의 정의된 위치로 바로 이동합니다. 마우스 없이도 빠르게 탐색 가능

🎮 게임 만들기

  • 비주얼 스튜디오에서 로컬 Windosw 디버거로 언리얼 엔진 실행
  • 레벨 생성 (MainLevel)
  • 캐릭터 생성 (CharacterBase)

    ⚠️ 해당 언리얼 프로젝트 따로 실행
  • 소스 파일에서 TickSetupPlayerInputComponent는 부모 클래스의 기능을 그대로 호출 ➡ 헤더 파일에서는 해당 선언을 삭제해도 됨
  • 이 캐릭터 베이스를 기반으로 적 AI(Enemy)와 플레이어 캐릭터 모두 상속받아 사용할 수 있다

✅ UPROPERTY 적용 기준: FullHP vs CurrentHP

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

	UPROPERTY(EditAnywhere)
	int32 FullHP;

	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
	int32 AttackCount;

private:
	int32 CurrentHP;
	int32 CurrentHP;
  • HP 변수는 에디터에서 설정하는 것이 편하기 때문에 UPROPERTY로 선언
  • int32는 정수형 크기를 명확히 지정하는 타입
    • 일부 플랫폼에서 int는 2바이트 또는 4바이트로 다를 수 있음
    • int32를 사용하여 항상 32비트(4바이트)로 고정
  • CurrentHP는 에디터에서 설정할 필요가 없기 때문에 UPROPERTY로 지정하지 않아도 된다

⭕ 왜 FullHPUPROPERTY() 붙였을까?
: 보통 FullHP는 설정값(기본 체력)

  • 에디터에서 조정 가능
  • 블루프린트에서 접근 가능
  • 저장, 로딩, 복제 등의 시스템이 관리함

CurrentHP에는 왜 안 붙였을까?

  • 보통 CurrentHP는 런타임 중에만 변경되고 에디터에서 수정할 필요가 없는 값이기 때문
  • 순수하게 코드 내부에서만 관리되는 값이라면 UPROPERTY() 안 붙여도 됨

⚠️ 예외
CurrentHP에도 이런 이유로 UPROPERTY() 붙일 수 있음

  • 블루프린트에서 현재 체력 접근해야 할 경우 ➡ BlueprintReadOnly
  • 세이브/로드 시스템에 포함해야 할 경우
  • 멀티플레이어에서 복제 필요할 경우 ➡ Replicated
변수UPROPERTY 필요?이유
FullHP⭕ 보통 붙임초기값 설정, 에디터/블루프린트 노출
CurrentHP❌ or ⭕ 상황에 따라런타임 내부 사용만이면 생략, 그 외엔 붙임

✅ public / protected / private

  • publicprivate 접근 지정자를 구분하여 코드 가독성과 캡슐화 개선
접근 지정자접근 가능 대상주로 넣는 멤버 예판단 기준 질문
🔵 public누구나 (외부 클래스 포함)외부에서 접근해야 하는 값, 함수 인터페이스 등외부 클래스가 직접 접근해야 해?
🟡 protected자식 클래스까지만자식 클래스에서 사용하는 설정 값, 재정의될 변수 등자식 클래스만 접근하면 돼?
🔴 private자기 클래스 내부만내부 상태 관리용 변수, 외부에 숨겨야 하는 값자기 클래스에서만 써야 안전해?

🟡 protected

  • BeginPlay()는 엔진에서 자동으로 호출되는 함수로, 자식 클래스에서 Super::BeginPlay() 호출 후 추가 로직을 작성할 수 있도록 protected로 지정
  • FullHP, AttackCount는 게임 로직상 자식 클래스에서 값을 읽거나 수정할 가능성이 있으므로 protected에 두기

🔴 private

  • CurrentHP는 외부나 자식 클래스가 직접 접근해서 변경하면 안 되므로 private으로 설정
  • 내부에서만 값을 관리하고, 외부에서는 TakeDamage() 같은 함수를 통해 간접적으로 접근하도록 설계

✅ Attack 함수 설계: virtual vs override

public;
	void Attack();
	void Hit(int32 Demage);
	void IncreaseKillCount();

	UPROPERTY(EditAnywhere)
	int32 FullHP;

	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
	int32 AttackCount;

	UPROPERTY(EditAnywhere)
	int32 Strength;
public:
	virtual void Attack();
  • Attack 함수는 플레이어와 적 각각 다르게 동작해야 함
    virtual 키워드를 사용하여 가상 함수로 선언

👩 virtral

  • 부모 클래스에서 virtual로 선언된 함수는 자식 클래스에서 재정의(override) 할 수 있음
  • 부모 클래스의 포인터나 참조를 통해 접근하더라도 실제 자식 객체의 함수가 호출됨
    ➡ 런타임에 올바른(자식의) 함수가 실행되도록 보장
  • 부모 클래스를 통해 공통 인터페이스를 제공하면서 자식 클래스마다 서로 다른 동작을 구현할 수 있음

👶 override

  • 부모 클래스의 virtual 함수를 자식 클래스에서 다시 정의하는 것
  • 함수 이름과 매개변수가 같아야 하며 실행 시 부모가 아닌 자식 클래스의 함수가 호출됨

🧩 예시

#include <iostream>
using namespace std;

class Animal {
public:
    virtual void sound() {
        cout << "동물이 소리를 냅니다" << endl;
    }
};

class Dog : public Animal {
public:
    void sound() override {  // ← 이게 오버라이드
        cout << "멍멍!" << endl;
    }
};

int main() {
    Animal* a = new Dog();
    a->sound();  // "멍멍!" 출력
    delete a;
}

🧠 정리

용어
virtual부모 함수에 붙여서 자식에서 오버라이드 가능하게 만듦
override자식 함수에 붙여서 부모 함수 재정의하고 있다는 걸 명확히 표시

✅ InputAction에서 lookmove가 Vector2 타입인 이유

이 두 입력이 2차원 방향 정보를 다루기 때문

1️⃣ move가 Vector2인 이유

  • 방향키(WASD)나 조이스틱은 좌우(X), 상하(Y) 방향 입력을 동시에 받을 수 있음
    (예) W + D 누르면 (1, 1) → 대각선으로 이동

  • move는 2D 평면상 이동 방향을 나타내는 벡터

2️⃣ look이 Vector2인 이유

  • 마우스나 오른쪽 스틱 입력으로 카메라를 좌우(X), 상하(Y) 로 움직임
    (예) 마우스를 위로 올리면 look.y가 양수

  • 이것도 2차원 방향을 의미하므로 Vector2

✅ uint8

  • 8비트의 int형
  • 정수형 데이터 타입
  • 0부터 255까지의 값 저장 가능 (2^8 = 256)
  • 음수는 없음 (unsigned)

0개의 댓글