![]() |
---|
.h 파일
#pragma once
: 헤더 파일의 중복 포함 방지를 위한 지시문#include "CoreMinimal.h"
: 언리얼 엔진의 주요 기능과 클래스를 제공하는 경량화된 헤더 파일#include "GameFramework/Actor.h"
: AActor를 상속받기 위한 헤더 파일#include "Item.generated.h"
: 언리얼 엔진의 리플렉션 시스템을 지원하기 위해 필요한 헤더 파일UCLASS()
, GENERATED_BODY()
매크로들도 리플렉션 시스템과 관련된 코드BASIC_API
: 클래스(AItem)를 외부로 Export하기 위한 매크로. 빌드할 때 필요한 매크로.cpp 파일
1. 루트 컴포넌트
![]() |
---|
루트 컴포넌트(Scene Component)는 리플렉션 시스템에 무조건 등록되게 되어 있어 추가 작업을 하지 않아도 에디터에서 볼 수 있음
현재 코드는 Static Mesh Component를 생성만 했지 시각적으로 보여지는 모델이 할당된 것은 아니기 때문에 언리얼 엔진 뷰포트에서도 아무것도 보이지 않는다
USceneComponent* SceneRoot
: 트랜스폼 정보를 갖는 USceneComponent의 포인터 SceneRootUStaticMeshComponent* StaticMeshComp
: Static Mesh를 렌더링하는 UStaticMeshComponent의 포인터 StaticMeshCompCreateDefaultSubobject<T>(TEXT("name"))
: 액터의 컴포넌트(T)를 생성할 때 사용하는 함수
- name은 에디터에서 식별할 이름
SetRootComponent(SceneRoot)
: 루트 컴포넌트를 지정하기 위한 함수로 루트 컴포넌트를 SceneRoot로 지정SetupAttachment(SceneRoot)
: 컴포넌트를 루트 컴포넌트에 붙이기 위한 함수
SetupAttachment()
는 매개변수로USceneComponent*
를 받는다
2. Mesh 및 Material 할당
Static Mesh : 3D 모델(정적 메쉬 데이터)
Material : Mesh의 표면 속성을 설정
Item 액터에 Static Mesh와 Material이 잘 적용된 것을 볼 수 있다.
그런데 1번 슬롯에 적용한 Material에 대해서는 아무런 변화가 없어 0번 슬롯을 주석으로 처리하고 1번 슬롯만 적용해보았다
1번 슬롯에 황금 Material을 설정 했는데(노란 박스) 아무런 변화가 없었다
에디터에서 원본 실린더 Static Mesh를 더블클릭해서 켜보니 Material slot이 하나만 있는 걸 볼 수 있었다
(아마 현재 코드는 Static Mesh의 Material slot에 "Debuff Material과 황금 Material"을 설정한 것이고 누굴 선택할지 정하지 않은 상태라서 default로 0번 슬롯이 선택되서 Debuff Material만 잘 적용되는 것 같다)
ConstructorHelper::FObjectFinder<T>
: 게임 에셋을 로드할 때 사용하는 유틸리티 클래스
- 에셋 경로를 문자열로 제공받아 리소스를 찾음
- 경로는 에디터에서 리소스 우클릭 → Copy Reference를 하면 가져올 수 있다
- 경로의 /Game == 프로젝트 폴더의 Content 폴더
.Succeeded()
: 에셋 로드 성공 여부 확인SetStaticMesh()
,SetMaterial()
: 성공적으로 로드한 Static Mesh와 Material을 Static Mesh Component에 설정
Material 슬롯이 2개인 Skeletal Mesh를 로드해서 0번 슬롯과 1번 슬롯에 각각 다른 Material을 적용해보니 잘 적용되는 걸 볼 수 있었다
0번 슬롯에는 황금 Material, 1번 슬롯에는 녹슬어버린 철 Material을 적용하니 각 부위마다 다르게 적용된 것을 볼 수 있었다
=> 슬롯을 늘릴 수 있음. 에디터에서 늘려도 되고 C++ 코드로도 늘릴 수 있음. 하지만 이게 잘 적용되고 안되고는 다른 문제임
슬롯을 추가해서 하나를 늘렸다고 해도 해당 슬롯의 머티리얼이 적용될 부분에 대한 작업을 하지 않았기 때문에 원하는 데로 작동하지 않음
그래서 위에 static mesh에 머티리얼 2개를 넣었을 때 0번 슬롯에 들어간 머티리얼만 적용된 것
3. 추가 구현
![]() |
---|
![]() | ![]() ![]() |
---|
추가하면서 알아야 할 것들에는 주석을 추가
그리고 헤더파일의 상단부에 #include "---.h"
를 추가하면 GENERATED_BODY() 매크로에 빨간 줄이 생기는데 그냥 빌드하고 실행해도 잘 동작한다. 하다보면 빨간 줄도 알아서 사라져있음
StaticClass()
UObject
와 그 하위 클래스를 동적으로 생성(클래스 인스턴스 생성)하는 NewObject<t>()
AActor
기반 클래스를 스폰(월드에 실제로 존재)하는 SpawnActor<T>()
NewObject
와 비슷한 역할을 한 이전 언리얼 버전에서 사용된 ConstructObject<T>()
UObject
의 서브 오브젝트를 생성하는 CreateDefaultSubobject<T>()
UGameplayStatics::SpawnEmitterAtLocation()
이렇게 Unreal Engine에서 제공하는 생성 함수를 사용해서 생성된 [객체]들은 모두 Unreal Engine의 Garbage Collection에 의해 관리된다
여기서 CreateDefaultSubobject<T>()
는 객체를 정적으로 생성시켜주는 함수
SpawnActor<T>()
로 동적 할당이 되기 때문에 이 컴포넌트들도 힙 메모리에 저장되고 액터가 제거될 때 함께 제거됨 CreateDefaultSubobject<T>()
함수 내부 코드를 따라가보면 FMemory::Malloc()
하는 부분을 찾을 수 있었다. 여기를 참고해서 실제로 어떤 식으로 메모리 할당이 되는지 확인해보자컴포넌트 생성 함수 메모리 할당
![]() |
---|
파란박스는 컴포넌트, 빨간 박스는 동적 배열, 연두 박스는 일반 int형 변수
=> CreateDefaultSubobject<T>()
는 컴포넌트는 생성할 때 동적 메모리를 할당된다.
언리얼에서의 정적 생성, 동적 생성라는 말이 메모리를 스택 메모리, 힙 메모리에 할당한다는 말이 아니라 객체가 world나 level에 언제 배치되는가에 대한 것
참조 사이트
1. https://rhksgml78.tistory.com/698
2. https://velog.io/@singery00/UE5-C-C%EB%A1%9C-%EC%96%B8%EB%A6%AC%EC%96%BC-%EC%BA%90%EB%A6%AD%ED%84%B0-%EC%83%9D%EC%84%B1%ED%95%98%EA%B8%B0-%E5%AE%8C
3. https://forums.unrealengine.com/t/how-to-change-character-capsule-component-location/366247
4. https://velog.io/@sobokii/UE5-Roll-Pitch-Yaw