코딩

UE5 C++ | Actor 좌표 이동·회전 구현

story98138 2026. 3. 23. 17:42

 오늘 한 것

언리얼 엔진 C++ 과제로 Actor의 좌표 이동 및 회전 시뮬레이션을 구현했다.
BeginPlay()에서 랜덤 이동과 회전을 10회 반복하고, 매 스텝마다 좌표를 화면에 출력하는 구조다.
도전 기능까지 포함해 50% 확률 이벤트 시스템10회 종료 후 결과 리포트도 완성했다.


 구현 구조 요약

AMyActor
├── BeginPlay()          ← 10회 루프 실행
├── Move(float Distance) ← X축 이동 + 좌표 로그
├── Turn(float Angle)    ← Yaw 회전 + 각도 로그
└── TriggerEvent()       ← 50% 확률 이벤트

헤더 (MyActor.h)

UCLASS()
class MYPROJECT_API AMyActor : public AActor
{
    GENERATED_BODY()

public:
    AMyActor();

protected:
    virtual void BeginPlay() override;

private:
    void Move(float Distance);
    void Turn(float Angle);
    void TriggerEvent();
};

소스 (MyActor.cpp)

void AMyActor::BeginPlay()
{
    Super::BeginPlay();

    // 시작 위치 설정
    SetActorLocation(FVector(0.f, 50.f, 0.f));

    int32 EventCount = 0;
    float TotalDistance = 0.f;
    FVector PrevLocation = GetActorLocation();

    for (int32 i = 0; i < 10; i++)
    {
        float RandDist  = FMath::RandRange(50.f, 200.f);
        float RandAngle = FMath::RandRange(0.f, 360.f);

        Move(RandDist);
        Turn(RandAngle);

        // 이동 거리 누적
        FVector CurrLocation = GetActorLocation();
        TotalDistance += FVector::Dist(PrevLocation, CurrLocation);
        PrevLocation = CurrLocation;

        // 이동 횟수 출력
        FString StepMsg = FString::Printf(TEXT("Step %d / 10"), i + 1);
        GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, StepMsg);

        // 50% 확률 이벤트
        if (FMath::RandRange(0, 1) == 1)
        {
            TriggerEvent();
            EventCount++;
        }
    }

    // 최종 리포트
    FString Report = FString::Printf(
        TEXT("=== RESULT === TotalDist: %.1f | Events: %d"), TotalDistance, EventCount);
    GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Green, Report);
}

void AMyActor::Move(float Distance)
{
    FVector NewLocation = GetActorLocation() + GetActorForwardVector() * Distance;
    SetActorLocation(NewLocation);

    FString Msg = FString::Printf(TEXT("Pos: %s"), *NewLocation.ToString());
    GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Cyan, Msg);
}

void AMyActor::Turn(float Angle)
{
    FRotator NewRotation = GetActorRotation() + FRotator(0.f, Angle, 0.f);
    SetActorRotation(NewRotation);

    FString Msg = FString::Printf(TEXT("Rot Yaw: %.1f"), NewRotation.Yaw);
    GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Orange, Msg);
}

void AMyActor::TriggerEvent()
{
    GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("[EVENT] Triggered!"));
}

 오늘의 핵심 : AddOnScreenDebugMessage 파라미터 정리

오늘 가장 헤맸던 부분이 바로 이 함수다.
파라미터가 4개인데 순서와 역할을 정확히 몰라서 처음엔 색이 안 나오거나 메시지가 쌓이지 않았다.

GEngine->AddOnScreenDebugMessage(
    int32 Key,          // [1] 메시지 식별 키
    float  TimeToDisplay, // [2] 화면 표시 시간 (초)
    FColor DisplayColor,  // [3] 텍스트 색상
    FString DebugMessage  // [4] 출력할 문자열
);

Key 값의 동작 차이가 핵심이다

Key 값                                        동작

-1 매번 새 줄로 추가 (로그처럼 쌓임)
0 이상 정수 같은 Key면 덮어씌움 (값 실시간 갱신용)

 

FString 변환 시 * 연산자 필수

// 컴파일 에러
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Cyan, NewLocation.ToString());

// 올바른 방법
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Cyan, *NewLocation.ToString());
// 또는
FString Msg = FString::Printf(TEXT("Pos: %s"), *NewLocation.ToString());
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Cyan, Msg);

FString을 직접 넘길 때는 *TCHAR*로 변환해야 한다.
Printf로 포맷팅하면 FString이 만들어지므로 그대로 넘겨도 된다.


오늘 새로 쓴 언리얼 API 정리

API 용도
GEngine->AddOnScreenDebugMessage() 화면에 디버그 텍스트 출력
FMath::RandRange(min, max) 범위 내 랜덤 정수/실수 반환
FVector::Dist(A, B) 두 벡터 간 거리 계산
GetActorForwardVector() 액터의 전방 방향 벡터 반환
FString::Printf(TEXT(...), ...) C의 printf 스타일 FString 생성

느낀 점

  • 언리얼 C++은 일반 C++과 문법은 같지만 타입 체계가 다르다.
    FString, FVector, FRotator 등 언리얼 전용 타입에 익숙해지는 게 먼저다.
  • AddOnScreenDebugMessage의 Key 파라미터를 이해하고 나니
    디버깅 전략 자체가 달라졌다. 값 갱신인지, 로그 누적인지를 의식적으로 선택하게 됐다.
  • BeginPlay()에서 루프를 돌리는 건 시각적으로는 한 프레임에 전부 출력된다.
    실제로 움직이는 것처럼 보이려면 Tick() 또는 타이머(FTimerHandle)가 필요하다는 걸 알았다 → 다음 챕터 예습 포인트.

Hollow Village Dev / Ironclad Studios