본문 바로가기

게임 개발/이득우의 언리얼 C++

[이득우의 언리얼 C++ 게임개발의 정석] #2. 액터의 설계

반응형

이득우의-언리얼-C++-게임개발의-정석-표지

<1>. 언리얼 콘텐츠의 구성 요소

<1> - 1. 월드 : 게임 콘텐츠를 구동하기 위해 필요한 필수적인 환경을 의미한다.

                         ex) 공간, 시간, 물리 법칙, 렌더링...

<1> - 2. 액터 : 콘텐츠를 구성하는 최소 단위의 물체 / '배우'처럼 자신의 역할을 수행하는 오브젝트.

※구성요소

  • 이름
  • 유형 : 액터의 역할 / 액터의 클래스 이름
  • 트랜스폼
  • 프로퍼티 : 액터에 설정된 속성 값.
  • 게임 로직 : 코드

<1> - 3. 레벨 : 스테이지

 

<1> - 4. 컴포넌트 : 액터가 가질 수 있는 다양한 기능들을 규격화한 것.

  • 스태틱메시 컴포넌트 : 애니메이션이 없는 모델링 에셋 / 시각적, 물리적 기능 제공.
  • 스켈레탈메시 컴포넌트 : 애니메이션이 있는 모델링 에셋 / 시각적, 물리적 기능과 애니메이션 제공.
  • 콜리전 컴포넌트 : 구/박스/캡슐로 지정한 영역에 물리적인 기능을 설정 / 시각적 기능은 없음.
  • 카메라 컴포넌트 : 월드에서 보이는 상황을 모니터로 보여주는 기능.
  • 오디오 컴포넌트 : 소리를 발생시키는 기능.
  • 파티클 시스템 컴포넌트 : 파티클 시스템으로 설계된 이펙트를 보여주는 기능.
  • 라이트 컴포넌트 : 물체에 광원 효과를 부여하는 기능.
  • 무브먼트 컴포넌트 : 움직임을 부여하는 기능.

 

액터는 여러 개의 컴포넌트를 가질 수 있으며,

그중에서 대표하는 하나의 컴포넌트를 반드시 지정해야 한다.  이를 루트 컴포넌트 라고 한다.

 

왜냐하면 액터의 트랜스폼, 물리 처리 등 기반을 잡고 있을 컴포넌트가 하나 있어야 효율적이기 때문!

 

<2>. 액터의 설계 - 물이 흐르는 분수대 액터 만들기

분수대가 필요하고 물이 필요하다. 둘은 스테틱메시 컴포넌트인 것을 알 수 있다.

→ 분수대 액터의 멤버 변수로 2개의 UStaticMeshComponent 클래스의 포인터를 선언해줘야 한다.

     (헤더파일의 'CoreMinimal.h'를 'EngineMinimal.h'로 변경해 줘야 클래스 정보를 참조할 수 있다.)

UStaticMeshComponent* Body;
UStaticMeshComponent* Water;

 

→포인터를 선언 → 메모리 동적 할당 → 명시적으로 객체를 소멸시켜야 차후 메모리 관리 문제 안 생김

'UPROPERTY()' 매크로 사용하면 객체 자동 관리 가능. 

UPROPERTY()
UStaticMeshComponent* Body;

UPROPERTY()
UStaticMeshComponent* Water;

 

액터의 구축은 클래스의 생성자 코드(Fountain.cpp)에서 진행된다.

생성자 코드에서 컴포넌트를 생성하는 함수는 'CreateDefaultSubobject'이다. 

Body = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("BODY"));

Water = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("WATER"));

 

※ "BODY", "WATER" 같은 문자열은 액터에 속한 컴포넌트를 구별하기 위한 Hash값 생성에 사용된다.

 

이제 루트 컴포넌트를 지정해야 한다. (SetupAttachment)

RootComponent = Body;
Water->SetupAttachment(Body);

 

! 주의!책 예제에서는 이렇게만 해도 에디터에서 Body, Water를 확인할 수 있지만, 실제로는 루트컴포넌트인 Body만 보인다. UPROPERTY() 함수에 'VisibleAnywhere'을 해줘야만 Water까지 보인다.

 

<3>. 액터와 에디터 연동

두 스태틱메시 컴포넌트가 생성됐으니, 에디터에서 속성 값을 편집해 보자. (VisibleAnywhere)

 

루트 컴포넌트인 Body에 분수대 에셋을 넣고, Water에 물 에셋을 넣는다.

 

<4>. 액터 기능의 확장

그냥 Water에 물 에셋을 넣으면, 위치가 이상하다. Water 컴포넌트의 위치의 기본값을 설정하는 방법을 알아보자.

'SetRelativeLocation' 함수를 이용하면 컴포넌트의 기본 위치 값을 변경할 수 있다.

→ 위치 값은 구조체 'FVector'를 사용해 표현한다.

Water->SetRelativeLocation(FVector(0.0f, 0.0f, 135.0f));

 

<5>. 에셋의 지정

여태까진 Fountain 액터의 컴포넌트에 에셋을 넣는 거였지만, 이제는 아예 Body 컴포넌트에 스태틱메시 에셋을 불러들여 설정 코드를 구현해 보자.

 '레퍼런스 복사'를 통해 경로를 불러온다.

이제 경로를 통해 에셋을 불러와야 한다. 'ConstructorHelpers' 클래스,  'FObjectFinder' 클래스를 사용한다.

→ 에셋의 경로 정보는 바뀔 일이 없으니 static으로 선언을 해주자.

static ConstructorHelpers::FObjectFinder<UStaticMesh>
	SM_BODY(TEXT("/Game/InfinityBladeGrassLands/Environments/Plains/Env_Plains_Ruins/StaticMesh/SM_Plains_Castle_Fountain_01.SM_Plains_Castle_Fountain_01"));

if (SM_BODY.Succeeded())
{
	Body->SetStaticMesh(SM_BODY.Object);
}

 

 

 

[이득우의 언리얼 C++ 게임개발의 정석] #3. 움직이는 액터의 제작

1. 프로그래밍 환경을 편리하게 만들어줄 매크로를 설정하고,이를 사용해 게임에서 액터가 어떻게 생성되고, 액터에서 어떤 이벤트가 발생하는지 확인해 본다.2. 로직을 구현해 움직임을 부여하

lbto.tistory.com

 

반응형