[UE5 TIL] Day 29 - Chpt 3 시작. 언리얼 컴포넌트

JungHoon Eum·2026년 4월 6일
post-thumbnail

키워드

  • Unreal Engine 컴포넌트, Component 생성
  • vector swap

기억해야 할 것

  • 조건으로 엔딩을 낼 경우(500번 돌린 후에 포기하기 등) 해당 회차에 실제로 끝이 난건지, 해당 회차에도 끝이 안난건지 확인하기
  • std::vector<int>().swap(v);
  • USceneComponent* SceneRoot;
  • 객체이름 = CreateDefaultSubobject<T>(TEXT("객체이름"));
  • SetRootComponent(객체이름);
  • StaticMeshComp->SetupAttachment(SceneRoot);
  • static ConstructorHelpers::FObjectFinder 객체이름 <T> (TEXT("오브젝트주소"))
  • SetMaterial(0, MaterialAsset.Object)

[코드카타] 콜라츠 추측

문제 링크

문제 요약

  • 입력된 수가 짝수라면 2로 나눕니다.
  • 입력된 수가 홀수라면 3을 곱하고 1을 더합니다.
  • 결과로 나온 수에 같은 작업을 1이 될 때까지 반복합니다.

내가 제출한 코드

#include <string>
#include <vector>

using namespace std;

int solution(int num) {
    long long number = num;
    int answer = 0;
    int count = 0;
    while(number>1&&count < 500)
    {
        if(number%2==0)
        {
            number /=2;
            count++;
            continue;
        }
        else
        {
            number = number*3+1;
            count++;
            continue;
        }
    }
    if(count >=500)
    {
        answer = -1;
    }
    else
    {
        answer = count;
    }
    
    return answer;
}

피드백

  • long long으로 받은 점은 Good
  • while 조건도 깔끔
  • 다만 500번째 연산에서 정확히 1이 되는 경우를 조심해야 했다.

배운 점

  • continue; 는 아랫부분 무시하고 다시 반복문 돌리는 것. 이 경우는 필요 없었음. break; 대체도 답이 아님.
  • 조건을 확인 잘 할 것 -> X 숫자에서 끝나는 건지 X숫자에서도 안끝난 건지 확인
  • 로컬 히스토리 for visual studio 괜찮다. 라이더는?라이더는?라이더는? 기본장착

언리얼 기초 라이브세션

  • 일단은...한동안은 몰래라도 듣자. 필요없는 부분이라도

  • std::vector<int>().swap(v); -> 빈 벡터() 를 벡터 v 랑 스왑해서 벡터 clearcapacity 도 0으로 만드는 거와 비슷하게 작동. 스왑 한 후 기존 벡터는 () 벡터 스코프가 다음 줄에 끝나면서 소멸

  • #include "generated.h"는 무조건 제일 밑에!!! 이건 Unreal Header Tool이 다른 파일들 다 확인하고 만들어주는 언리얼 전용 헤더다.

C++ 언리얼엔진 3D 게임 개발

언리얼 엔진 C++ 빌드 프로세스 이해하기

Visual Studio C++ 빌드 설정

  • DebugGame, DebugGame Editor, Development, Development Editor, Shipping...
  • DebugGame 모드 -> 디버깅에 최적화 되어 있는 모든. 디버그에 대한 모든 정보를 가진 채 게임이 빌드가 된다. 따라서 무거움.
  • DebugGame, DebugGame Editor 차이는? DebugGame -> 실행 파일 그 자체가 달랑 나옴. 엔진 코드들은 "고정" 이 된 채로 디버깅 가능.
    • DebugGame Editor는 에디터에서 플레이하면서 디버깅
  • Development, Development Editor -> 빠르게 개발하고-> 수정하고 반복할 때. 많이 축소가 되어 있고 빠르다. 적당한 수준의 가벼운 디버깅도 가능. Editor 안붙어있으면 Unreal Engine Editor 형식으로 빌드가 되지 않고 실행파일로 나옴.
  • Shipping -> 최종 릴리즈 단계. 디버그 정보 등등 모두 빠지고 빨라진다.

Visual Studio C++ 빌드하기

  • 원래 VisualStudio에서 쓰던 Build Solution 단축키 -> Ctrl+Shift+B: 엔진이나 유틸리티 등 포함 전체를 빌드함. 너무 느림
  • 부분 빌드: 게임 프로젝트 코드만 빌드 해도 된다. Solution Explorer에서 프로젝트 우클릭하고 Build
  • 언리얼 에디터 켜 놓고 빌드하지 말 것! 켜 놓은 상황에선 dll 수정 안 됨. 에러 뜨면 일단 에디터 끄고 다시 빌드해 볼 것.
  • Build + IntelliSense: IntelliSense는 실제 에러가 아니라 컴파일러 자체의 진짜 에러는 아니다. Unreal 자체 문법을 감안 안하기 때문에 끄는게 맞다.
  • 비쥬얼 스튜디오로 빌드 하면 Binaries 폴더 안에 Win64dll 파일이 생성 -> 이제 언리얼 에디터 실행하면 이 수정된 dll 파일 로드 해서 수정 사항 반영.

Live Coding

  • 에디터 종료하지 않은 상태에서 C++ 코드 수정, 에디터에 반영 가능.
  • 함수 내부 로직, 변수 값변경, 로그 출력 변경 등은 가능
  • 안되는 경우
    • UCLASS, USTRUCT, UENUM 매크로의 추가·삭제·수정
    • 새로운 C++ 클래스 (.h/.cpp) 생성
    • 엔진 소스 코드 (Engine 폴더 내 코드) 변경
    • 함수 시그니처 (인자, 반환값)나 클래스 상속 구조 변경
  • 활성화, 비활성화는 Unreal Editor 우 하단에 테트리스 같이 생긴 놈에서 가능.
  • 비쥬얼 스튜디오에서 수정한 거 컨트롤 쉬프트 S 해서 저장 -> 언리얼 에디터에서 라이브 코딩 버튼 누르기.

빌드 문제 복구하기

  • C++ 코드 수정/빌드 완료했는데도 반영 안 될 때 많다.
  1. 언리얼 에디터, Visual Studio 종료
  2. 프로젝트 폴더에서 Intermediate, DerivedDataCache, Saved 폴더 삭제
  3. .uproject 파일 Shift 우클릭 -> Generate Visual Studio project Files.
  4. Visual Studio 키고 클린 빌드 수행(비쥬얼 스튜디오 상단 툴바에 Build 에서 Clean Solution). 언리얼 에디터 다시 실행.
  • 문제 해결 안 되면 Saved/Logs 확인하기.

C++ Actor 클래스 생성 및 삭제하기

  • Migrate -> 다른 프로젝트에서 파일 잘라내기-> 붙여넣기의 언리얼용으로 Dependency 등 깨지지 않게 잘 붙여넣어 주는 기능.
  • 오브젝트와 액터의 차이: 오브젝트(객체) 는 언리얼 내 모든 클래스의 뿌리. 모두가 UObject 상속받음
  • 오브젝트는 맵에 배치 불가. 추상 클래스임. 데이터/로직 담당.
  • 액터는 월드에 배치할 수 있는 모든 클래스를 통칭. 좌표 정보를 갖는다.
  • 데이터를 담는 구조(플레이어 스테이터스 등등) < 이런 건 오브젝트를 상속받음.
  • 신규 Public Actor 클래스 Item 을 만든 스샷 -> 여기서 솔루션 SpartaProject 아래 Source-> SpartaProject 가 하나의 "모듈" 인 것. 지금은 한 폴더 아래 다 관리하지만 나중엔 플레이어 폴더 하나(모듈 하나), UI 모듈...이런 식으로 관리하게 된다.
  • Public 클래스는 헤더가 Public에, cpp 소스 코드가 Private에 생성. 이러면 다른 모듈에서 이 헤더를 include, 참조 가능함.
  • 언리얼 에디터 -> Tools -> New C++ Class로 새 클래스 생성 가능.
    • Visual Studio에서 New Item 해서 생성이 가능하긴 하지만...설정해야 할 부분들이 많다.\
  • 클래스 삭제 -> Visual Studio에서 Remove? 안됨
    • Visual Studio에서 Remove 후 실제 프로젝트 폴더 - Source -> Public 폴더와 Private 폴더에서 실제 파일까지 삭제 해야 삭제된다.

Actor 클래스에 컴포넌트 추가

.h 파일

#pragma once

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

UCLASS()
class SPARTAPROJECT_API AItem : public AActor
{
	GENERATED_BODY()
	
public:	
	AItem();

protected:	
	virtual void BeginPlay() override;

public:		
	virtual void Tick(float DeltaTime) override;

};
  • #pragma once 컴파일러가 중복 참조 한번씩만 처리하도록 하는 코드
  • #include "CoreMinimal.h": 언리얼 기본 헤더. 엔진 전역 타입, 매크로, 함수. .h 맨 위에 거의 항상 포함
  • #include "GameFramework/Actor.h": AActor 클래스 선언용
  • #include "Item.generated.h": 언리얼 헤더툴이 자동 생성하는 코드용. 무조건 헤더 마지막 줄에
  • UCLASS(), GENERATED_BODY() -> 리플렉션 시스템에 등록, 사용.
  • 접두사 규칙: A (Actor 계열), U (Object 계열), F (구조체), T (템플릿), E (열거형) 등
    • 우리가 만든 Item 클래스는 액터이므로 AItem
  • SPARTAPROJECT_API -> 앞에는 보통 모듈명(현재는 SpartaProject) _API는 다른 모듈에서도 사용할 수 있게 하기 위한 매크로
  • AItem();은 생성자, BeginPlay()Tick은 블루프린트에서 본 그 이벤트 함수.

.cpp 파일

#include "Item.h" 
// 생성자 구현부
AItem::AItem()
{
		PrimaryActorTick.bCanEverTick = true; 
}

// BeginPlay() 구현부
void AItem::BeginPlay()
{		
		Super::BeginPlay();
}

// Tick() 구현부
void AItem::Tick(float DeltaTime)
{		
}
  • #include "Item.h"는 항상 가장 먼저 include 해야 한다.
  • SUPER:: 부분은 부모 클래스(AActor) 부분들 먼저 호출한다

컴포넌트 - 씬 루트 추가

  • 헤더에 USceneComponent* SceneRoot; 선언
    • SceneComponent에 대한 포인터 SceneRoot 를 선언하는 것.
  • 소스코드에 SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));
    SetRootComponent(SceneRoot); 추가
    • CreateDefaultSubobejct<> 는 템플릿 -> 저 <> 안에 원하는 오브젝트 타입을 넣는 것. TEXT 뒤에 "" 해서 넣는 건 이름
    • SetRootComponent(); 로 루트 컴포넌트 지정

컴포넌트 - 스태틱 메쉬 추가

  • 헤더에 UStaticMeshComponent* StaticMeshComp; 로 포인터 선언
  • 소스코드에 StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh")); 추가
  • StaticMeshComp->SetupAttachment(SceneRoot);: StaticMeshComp 는 헤더에서 선언한 포인터라 -> 쓴다. SetupAttachment로 씬루트 아래에 추가. 루트 아래 추가 안하면 여러모로 복잡해짐.

컴포넌트 - 메쉬에 실제 메쉬/마테리얼 추가

static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshAsset(TEXT("/Game/Resources/Props/SM_Chair.SM_Chair"));
		if (MeshAsset.Succeeded())
		{
			StaticMeshComp->SetStaticMesh(MeshAsset.Object);
		}

		static ConstructorHelpers::FObjectFinder<UMaterial> MaterialAsset(TEXT("/Game/Resources/Materials/M_Metal_Gold.M_Metal_Gold"));
		if (MaterialAsset.Succeeded())
		{
			StaticMeshComp->SetMaterial(0, MaterialAsset.Object);
		}
  • static ConstructorHelpers::FObjectFinder<> 역시 템플릿. <> 안에 원하는 오브젝트 형식을 넣는다. (TEXT("")) 안에 원하는 리소스의 주소를 넣는다.
  • 위의 경우 MeshAsset 또는 MaterialAsset 이라는 이름의 객체를 생성하는 코드라고 보면 된다.

  • 쓰고 싶은 마테리얼이나 메쉬를 컨텐츠 브라우저에서 Copy Reference
    • 이러면 주소가 / Script / Engine.Material'/Game/Resources/Materials/M_Metal_Gold.M_Metal_Gold' 이렇게 나온다. 여기서 /Game 부터가 진짜 주소이므로 그 전 부분은 삭제하고 삽입.
  • MeshAsset.Succeeded() 로 불러오기 성공했는지 체크. SetMaterial SetStaticMesh 로 실제 대입.
    • 마테리얼의 경우 여러 부위가 있으므로 SetMaterial(0, MaterialAsset.Object) 형태임에 주의
  • 마테리얼 인스턴스는 UMaterial 부분에 UMaterialInstance 를 넣으면 된다.
profile
개발지망생

0개의 댓글