C++과 Unreal Engine으로 3D 게임 개발 3

김여울·2025년 7월 2일

내일배움캠프

목록 보기
35/139

📍 1주차 6강 ~ 7강

Transform

종류

월드 좌표계

  • 게임 월드 전체에서의 위치
  • (x=100, y=200, z=50)에 위치 → 이 좌표는 월드 좌표계에서 정의됨

로컬 좌표계

  • 부모 객체를 기준으로 한 상대적인 좌표
  • 자식 객체가 부모 객체의 좌표계 안에서 얼마나 떨어져 있는지
  • 부모가 이동하면 자식도 같이 이동
  • 부모 객체의 위치가 (100, 100, 0)이고
    자식 객체의 로컬 좌표가 (50, 0, 0)이라면
    → 자식 객체의 월드 좌표는 (150, 100, 0)이 됨

Transform - Lifecycle

BeginPlay

월드에 스폰된 직후에 딱 나타나서 위치 옮기면 됨
BeginPlay()에 구현해야함

void AItem::BeginPlay()
{
	Super::BeginPlay();
	SetActorLocation(FVector(x, y, z));	// 월드 좌표를 이동시킴
	SetActorRotation(FRotator(pitch, yaw, roll));	// 회전
	SetActorScale3D(FVector(x, y, z));	// 크기
	// SetActorScale3D(FVector(2.0f, 2.0f, 2.0f)) 
	// → SetActorScale3D(FVector(2.0f))
    
    // FTransform 구조체로 한 번에 관리하기
    FVector NewLocation(300.0f, 200.0f, 100.0f);
    FVector NewRotation(0.0f, 90.0f, 0.0f);
    FVector NewScale(2.0f);
    
    FTransform NewTransform(NewRotation, NewLocation, NewScale);
    
    SetActorTransform(NewTransform);
}
회전 종류⚠️ 회전 축설명
PitchX 축상하 회전: 객체가 위로/아래로 회전하는 동작.
YawZ 축좌우 회전: 객체가 좌측/우측으로 회전하는 동작.
RollY 축좌우 비틀기: 객체가 자기 자신을 중심으로 회전하는 동작.

📎 TIL - Pitch / Yaw / Roll

void AItem::BeginPlay()
{
	Super::BeginPlay();	
	SetActorLocation(FVector(300.0f, 200.0f, 100.0f));	
	SetActorRotation(FRotator(0.0f, 90.0f, 0.0f));	
	SetActorScale3D(FVector(2.0f));	
}

▶ Play


Tick

의자를 계속 회전하게 만들자
매 프레임마다 Rotation 값이 변하면 됨
Tick()에 구현해야함

1초마다 90도씩 회전하게 만들기 → 자전 형태 = Local

// Item.h
float RotationSpeed;	// 변수 선언

// Item.cpp
// 생성자에서 초기화
AItem::AItem()
{
	PrimaryActorTick.bCanEverTick = true;	// Tick 켜기
	RotationSpeed = 90.0f;
}

void AItem::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
    if (!FMath::IsNearlyZero(RotationSpeed))
    AddActorLocalRotation(FRotator(0.0f, RotationSpeed * DeltaTime, 0.0f));
}

RotationSpeed * DeltaTime

  • RotationSpeed
    • 객체가 회전하는 속도
    • 이 값은 보통 한 프레임당 회전할 각도(예: 초당 회전할 각도)로 설정됨
  • DeltaTime
    - 이전 프레임과 현재 프레임 사이의 시간 간격
    - 프레임 레이트가 달라지더라도 회전이나 이동이 일정하게 유지되도록 도와줌
    - 사양이 달라도 동일하게 90도 회전할 수 있음

FMath::IsNearlyZero

  • 언리얼 엔진에서 제공
  • 주어진 값이 거의 0에 가까운지 확인
  • 부동 소수점 계산에서 발생할 수 있는 작은 오차를 고려해서 값이 사실상 0에 가까운지를 판단하는 데 유용함

Tick - 생성자

Tick은 Tick 함수를 켜야만 작동 가능 → 생성자에서 적용함

PrimaryActorTick.bCanEverTick = true;	// on
PrimaryActorTick.bCanEverTick = false;	// off 

리플렉션 시스템

블루프린트 - C++ 연동시켜 왔다갔다 구현 가능

클래스 리플렉션 (Class Reflection)

// Item.h
#include "Item.generated.h"	// 헤더파일 가장 아래 위치해야함

UCLASS()	
// 이 클래스를 리플렉션 시스템에 등록 
// → 블루프린트에서도 접근 가능해짐
class SPARTAPROJECT_API AItem : public AActor
{
	GENERATED_BODY()	// 리플렉션 데이터를 자동 생성하기 위해 언리얼 엔진이 사용하는 매크로
};
UCLASS() = UCLASS(Blueprintable, BlueprintType)
// 이 클래스가 블루프린트에서 상속 가능함
// BP에서 이 클래스를 변수로 선언 or 참조 가능

UCLASS(NotBlueprintable, BlueprintType) = UCLASS(BlueprintType)
// 이 클래스는 BP에서 상속 불가능
// BP에서 선언 or 참조 가능

Blueprintable 상속 가능

얘를 부모로 두고 BP Class를 만든다

부모로 둬서 스태틱 메시까지 그대로 상속 받음

BlueprintType 변수 가능


Item Class로 변수화
이 클래스를 BP 안에서 또 클래스로 만들어줌

변수 리플렉션 (Variable Reflection)

인자설명클래스 디폴트 값 수정 여부인스턴스 값 수정 여부
EditDefaultsOnly디폴트 값만 수정 가능하며, 인스턴스 값은 수정할 수 없습니다. 블루프린트에서는 기본값만 변경 가능합니다.수정 가능 (클래스 디폴트 값만)수정 불가
EditInstanceOnly인스턴스 값만 수정 가능하며, 디폴트 값은 수정할 수 없습니다.수정 불가수정 가능 (인스턴스 값만)
EditAnywhere블루프린트에서 해당 변수를 읽고 수정할 수 있습니다. 디폴트 값과 인스턴스 값 모두 수정 가능.수정 가능 (클래스 디폴트 값)수정 가능 (인스턴스 값)
VisibleAnywhere해당 변수를 어디서든 읽을 수 있지만, 수정은 불가능합니다. 인스턴스 값은 수정 불가.수정 불가수정 불가
BlueprintReadOnly블루프린트에서 변수 읽기만 가능, 디폴트 값을 수정할 수는 있지만 인스턴스 값 수정은 불가능.
get ⭕, set ❌
수정 가능 (클래스 디폴트 값만)수정 불가
BlueprintReadWrite블루프린트에서 변수 읽고 쓰기 가능, 디폴트 값과 인스턴스 값 모두 수정 가능.
get ⭕, set ⭕
수정 가능 (클래스 디폴트 값)수정 가능 (인스턴스 값)
Transient저장되지 않음, 디폴트 값이나 인스턴스 값 모두 저장되지 않고, 저장될 수 없음.수정 불가수정 불가
SaveGame해당 변수가 세이브 파일에 저장될 수 있도록 설정, 디폴트 값과 인스턴스 값 모두 저장됨.수정 가능 (클래스 디폴트 값)수정 가능 (인스턴스 값)
Category="CategoryName"카테고리로 변수를 그룹화할 수 있도록 설정. 디폴트 값을 설정하는 것과 관련 있음.수정 가능 (클래스 디폴트 값만)수정 불가
meta=(ClampMin="X", ClampMax="Y")변수의 최소값과 최대값을 설정하여 디폴트 값에 제한을 두지만, 인스턴스 값은 수정 가능.수정 가능 (클래스 디폴트 값만)수정 가능 (인스턴스 값)
  • ( ) 인자 없음 : 기능을 하는 클래스와는 다르게 변수와 함수에서는 언리얼이 존재만 알고 있음
    UPROPERTY()
    USceneComponent* SceneRoot;	

디폴트 값

클래스 디폴트 값 (Default Values)

  • 클래스 차원에서 설정하는 초기값
  • EditDefaultsOnly로 선언하면 블루프린트에서 수정 불가
  • 자식 블루프린트에서 상속하면 디폴트 값 변경 가능
  • 객체가 생성되기 전에 적용됨

인스턴스 값 (Instance Values)

  • 객체가 생성된 후에 설정되는 값
  • 인스턴스마다 다르게 가질 수 있음
  • BlueprintReadWrite로 선언하면 블루프린트에서 수정 가능
UPROPERTY(EditDefaultsOnly)
float Health = 100.0f;  // 디폴트 값

UPROPERTY(BlueprintReadWrite)
float CurrentHealth;   // 인스턴스 값

블루프린트에서 디폴트값 수정 제한

  • 디폴트 값은 상속받은 블루프린트에서만 변경 가능
  • 인스턴스 값은 개별 객체마다 수정 가능
// Item.h
UCLASS()
class SPARTAPROJECT_API AItem : public AActor
{
	GENERATED_BODY()
	
public:	
	AItem();

protected:
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Item|Components")
	USceneComponent* SceneRoot;	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Item|Components")
	UStaticMeshComponent* StaticMeshComp;
    
    UPROPERTY(EditDefaultonly, BlueprintReadOnly, Category="Item|Properties")
	float RotationSpeed;

  • USceneComponent* SceneRoot;
    수정 불가능하게 해서 RootComponent는 뜨지도 않음
  • UStaticMeshComponent* StaticMeshComp;
    EditAnywhere은 뜸
  • float RotationSpeed;
    클래스 디폴트에선 수정 가능

함수 리플렉션(Function Reflection)

// Item.h
UFUNCTION(BlueprintCallable, Category="Item|Actions")
void ResetActorPosition();

UFUNCTION(BlueprintPure, Category="Item|Properties")
float GetRotationSpeed() const;

UFUNCTION(BlueprintImplementableEvent, Category="Item|Event")
void OnItemPickedUP();
  • BlueprintCallable 블루프린트에서 호출 가능
  • BlueprintPure BP에서 return 값만 반환 받게 호출, 실행 핀은 없음
  • BlueprintImplementableEvent BP에서 구현 필요, 호출은 C++에서도 가능함
// Item.cpp
void AIItem::ResetActorPosition()
{
    SetActorLocation(FVector::ZeroVector);	// 원점 위치
}

float AIItem::GetRotationSpeed() const
{
    return RotationSpeed;
}

// OnItemPickeUp() 은 구현하지 않고 BeginPlay에서 호출만

1개의 댓글

comment-user-thumbnail
2025년 7월 10일

b

답글 달기