Unreal Track 1기 [25.01.24] - C++와 Unreal Engine으로 3D 게임 개발 :: 1주차 (4)

chooha·2025년 1월 24일

TIL

목록 보기
28/60

< 액터 이동/회전 >

1. 부모-자식 관계의 Transform 함수

▸ GetRelativeTransform()

부모 기준의 상대적인 위치/회전/스케일 값을 가져옴

▸ SetRelativeLocation(), SetRelativeRotation()

부모 기준으로 자식의 위치/회전 값을 조정함


2. Tick()함수로 이동/회전 구현

▸ Tick함수 고려해야 할 점

  • FPS(Frame Per ecSond) : 초당 몇 프레임을 연산 및 실행할 수 있는지

  • FPS의 값에 따라 플레이 환경이 달라 질 수 있음
    ex) 매 틱마다 1유닛 씩 변경되는 움직이는 발판을 만든다고 가정할 때,
    초당 100프레임을 연산하는 컴퓨터에서는 1초에 Tick함수가 100번 실행되고, 초당 30프레임을 연산하는 컴퓨터에서는 30번 실행됨
    이 말은 컴퓨터의 환경에 따라 게임 체감 속도가 달라질 수 있다는 것을 의미

▸ DeltaTime을 통한 보정

  • 위와 같은 문제때문에 나온 해결법이 DeltaTime이라는 개념임
  • DeltaTime은 1프레임을 연산하는 데 소요되는 시간을 말하고 변경하려는 값에 DeltaTime을 곱해줌으로써 프레임에 독립적으로 동작하게끔 구현할 수 있음
    ex) A라는 컴퓨터는 100fps, B는 50fps라면
    A는 1프레임을 연산하는데 0.01초가 걸리고 B는 0.02초가 소요됨
    Tick함수에서 DeltaTime을 이용해 어떤 값을 100만큼 변경시킨다고 가정했을 때,
    A환경에서는 프레임 당 100 * 0.01로 1만큼 변경되고, B환경에서는 100 * 0.02로 2만큼 변경됨
    이렇게 변경되는 횟수가 각각 100번, 50번이기 때문에 결과적으로 1초당 변경되는 값은 100으로 동일함

▸ 회전 예제

#include "Item.h"

AItem::AItem()
{
    PrimaryActorTick.bCanEverTick = true; // Tick함수 활성화 (생성자에서)
    RotationValue = 90.0f; // 회전값
}

void AItem::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

	// 액터의 로컬좌표를 기준으로 z축을 회전시킴
    AddActorLocalRotation(FRotator(0.0f, RotationValue * DeltaTime, 0.0f));
}
  • FRotator(Pitch, Yaw, Roll)
    당연히 X, Y, Z순의 값이 들어갈 줄 알았는데 다른 방향으로 회전해서 놀랐음

  • 월드 좌표 기준으로 회전하고 싶다면 AddActorWorldRotation()

▸ 이동 예제

#include "Item.h"

AItem::AItem()
{
    PrimaryActorTick.bCanEverTick = true;
    LocationValue = 100.0f; // 이동값
}

void AItem::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

	// 월드 좌표 기준으로 이동
    AddActorWorldOffset(FVector(0.0f, 0.0f, LocationValue * DeltaTime));
}


< 리플렉션 시스템 >

1. Blueprint와 C++의 역할

어느 하나만을 사용하는 것이 아니라 각각의 장점을 취해 섞어서 사용함

  • Blueprint 활용
    UI 제작, 간단한 이벤트 처리, 시각적 연출 등 빠른 프로토타이핑과 직관적인 로직 작성에 사용

  • C++ 활용
    높은 성능이 필요한 게임플레이 로직이나 엔진 레벨의 확장, 복잡한 수학 연산 등에 사용

2. 리플렉션(Reflection)이란?

C++ 클래스의 변수 및 함수 정보를 엔진 내부의 메타데이터 형태로 저장하고, 이를 에디터나 블루 프린트에서 활용할 수 있게 만들어주는 기술

▸ C++ 클래스 리플렉션

  • #include "클래스이름.generated.h"
    - 클래스의 리플렉션 및 엔진 통합에 필요한 코드가 들어있음
    ❗반드시 헤더파일의 가장 마지막 #include 구문 아래에 위치해야 함 (빌드 에러 발생 위험)

  • UCLASS()
    - 해당 클래스를 언리얼 엔진의 리플렉션 시스템에 등록한다는 의미
    - 이 매크로가 있어야 에디터 차원에서 이 클래스를 인식하고 사용할 수 있음
    - 만약 옵션을 주지 않으면 상속이 가능하고 변수로 참조 가능한 형태로 등록됨
    - 주요 옵션

    • Blueprintable : 블루프린트에서 상속 가능한 클래스로 만듦
    • NotBlueprintalbe : 블루프린트에서 상속할 수 없는 클래스로 만듦
    • BlueprintType : 블루프린트에서 변수나 참조로 사용할 수 있게 함 (상속 X)
  • GENERATED_BODY()
    - 클래스 내부에 필요한 리플렉션 정보를 자동으로 생성해 줌

▸ C++ 변수 리플렉션 - UPROPERTY()

  • 편집 가능 범위
    - VisibleAnywhere : Read only / Default, Instance
    - EditAnywhere : Read, Write / Default, Instance
    - VisibleDefaultOnly : Read only / Default
    - EditDefaultsOnly : Read, Write / Default
    - VisibleInstanceOnly : Read only / Instance
    - EditInstanceOnly : Read, Write / Instance

  • Blueprint 접근성
    - BlueprintReadOnly : Read only / Event Graph
    - BlueprintReadWrite : Read, Write / Event Graph

💡 Default, Instance, Event Graph
- Default : 뷰포트, 블루프린트 에디터창의 Details 패널에서 보임
- Instance : 뷰포트 Details 창에서만 보임
- Event Graph : 보이는 것 뿐아니라 Event Graph에서 사용할 수 있음

  • 카테고리
    - Category = "카테고리 이름"
    - Transform 항목 바로 아래 표시됨

  • 메타 옵션 지정자
    - meta = (ClampMin = "0.0")
    에디터에서 변수 입력 시 최소값을 제한할 수 있음
    - meta = (AllowPrivateAccess = "true")
    해당 멤버가 private로 선언되어 있어도, 에디터나 Blueprint에서 접근할 수 있도록 허용

    언리얼 문서 - 메타 데이터 지정자

▸ C++ 함수 리플렉션 - UFUNCTION()

  • Blueprint 관련 지정자
    - BlueprintCallable
    Event Graph에서 호출 가능한 함수로 만듦
    - BlueprintPure
    Getter 역할만 수행 (Exec핀 없음)
    - BlueprintImplementableEvent
    함수의 선언은 C++에 있고, 구현은 블루프린트에서 하도록 함

< 참고 자료 >

언리얼 Tick, DeltaTime

0개의 댓글