C++ 전용

언리얼 엔진으로 작업을 시작하는 게임플레이 프로그래머를 위한 입문 정보입니다.

Windows
MacOS
Linux

C++ 클래스 마법사 를 사용하면 프로젝트에 새로운 C++ 클래스를 쉽게 추가할 수 있습니다. 새 클래스를 파생시키고자 하는 클래스를 선택한 이후, 마법사는 필수 헤더 파일과 소스 파일을 구성해 줍니다. 프로젝트에 처음 추가한 코드인 경우, 프로젝트는 코드 프로젝트로 전환되며, 소스 코드가 들어있는 게임 모듈이 생성됩니다. 언리얼 에디터에게 게임 모듈이 존재한다 알려주기도 하여, Visual Studio 나 XCode 에서의 C++ 변경내용을 로드하고 간단한 코드 변경같은 경우는 언리얼 에디터 안에서 컴파일되도록 해 주기도 합니다.

C++ 만 사용해서 구성된 LightSwitch 클래스 이름은 LightSwitchCodeOnly 이며, 아래에 설명되어 있습니다.

클래스 셋업

LightSwitchCodeOnly 클래스는 C++ 클래스 마법사 를 사용해서 생성되었으며, 부모 클래스로 Actor 를 선택했습니다.

LightSwitchCodeOnly.h 헤더 파일에는 클래스 선언이 들어있습니다.

UCLASS()
class [PROJECTNAME]_API ALightSwitchCodeOnly : public AActor
{
GENERATED_BODY()

};

C++ 클래스 마법사 로 생성된 클래스 선언은 자동으로 앞에 UCLASS() 가 붙습니다. UCLASS() 매크로는 엔진이 클래스를 인식할 수 있도록 하며, 키워드 지정자와 함께 사용하여 엔진 내에서의 클래스 작동방식을 설정할 수도 있습니다.

클래스 선언에는 변수 및/또는 함수 선언이 포함됩니다. 그 앞에는 각각 UPROPERTY()UFUNCTION() 매크로가 붙을 수 있으며, UCLASS() 매크로와 비슷한 역할을 합니다. 컴포넌트는 UPROPERTY() 매크로로 구성되기도 합니다.

LightSwitchCodeOnly.h 에서, C++ 가 사용된 부분은:

  • PointLightComponent 와 SphereComponent 를 선언합니다. PointLightComponent 와 SphereComponent 는 VisibleAnywhere (어디서나 보이게) 만들어집니다. 즉 그 프로퍼티를 LightSwitchCodeOnly 액터의 디테일 탭에 보인다는 뜻입니다.

    public:
    /** 포인트 라이트 컴포넌트 */
    UPROPERTY(VisibleAnywhere, Category = "Switch Components")
    class UPointLightComponent* PointLight1;
    
    /** 구체 컴포넌트 */
    UPROPERTY(VisibleAnywhere, Category = "Switch Components")
    class USphereComponent* Sphere1;
  • 생성자를 선언, 컴포넌트와 변수에 대한 기본값을 설정할 수 있도록 합니다:

    ALightSwitchCodeOnly();
  • OnOverlapBeginOnOverlapEnd 을 선언, 다른 액터가 구체 컴포넌트에 들어서거나 나설 때 호출되는 함수입니다. 참고로 얘들에는 시그너처가 다릅니다.

    /** 무언가가 구체 컴포넌트에 들어설 때 호출 */
    UFUNCTION()
    void OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
    
    /** 무언가가 구체 컴포넌트를 나설 때 호출 */
    UFUNCTION()
    void OnOverlapEnd(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
  • ToggleLight 선언, 포인트 라이트 컴포넌트의 표시여부를 토글하는 함수입니다.

    /** 라이트 컴포넌트의 표시여부 토글*/
    UFUNCTION()
    void ToggleLight();
  • DesiredBrightness 변수를 선언하고 VisibleAnywhere 지정자로 어디서든 보이게 만듭니다. LightSwitchCodeOnly 액터의 디테일 탭 내 Switch Properties 카테고리 안에 표시됩니다. 플로트 변수처럼 서브오브젝트가 아닌 변수의 경우, VisibleAnywhere 지정자는 그저 변수가 디테일 탭에 표시되도록 해 줄 뿐입니다. EditAnywhere 지정자를 사용할 수도 있지만, DesiredBrightness 변수는 액터가 레벨에 추가되었을 때만 사용되기에, 변수를 편집가능으로 만들 필요는 없습니다.

    /** 라이트의 선호 밝기 */
    UPROPERTY(VisibleAnywhere, Category="Switch Variables")
    float DesiredIntensity;

결과 헤더 파일은 이렇습니다:

LightSwitchCodeOnly.h

    // Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.

    #pragma once

    #include "GameFramework/Actor.h"
    #include "LightSwitchCodeOnly.generated.h"

    /**
     * 
     */
    UCLASS()
    class [PROJECTNAME]_API ALightSwitchCodeOnly : public AActor
    {
        GENERATED_BODY()
        public:
        /** 포인트 라이트 컴포넌트 */
        UPROPERTY(VisibleAnywhere, Category = "Switch Components")
        class UPointLightComponent* PointLight1;

        /** 구체 컴포넌트 */
        UPROPERTY(VisibleAnywhere, Category = "Switch Components")
        class USphereComponent* Sphere1;

        ALightSwitchCodeOnly();

        /** 무언가가 구체 컴포넌트에 들어설 때 호출 */
        UFUNCTION()
        void OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

        /** 무언가가 구체 컴포넌트를 나설 때 호출 */
        UFUNCTION()
        void OnOverlapEnd(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

        /** 라이트 컴포넌트의 표시여부 토글*/
        UFUNCTION()
        void ToggleLight();

        /** 라이트에 대한 선호 밝기 */
        UPROPERTY(VisibleAnywhere, Category = "Switch Variables")
        float DesiredIntensity;

    };

C++ 클래스 마법사 는 클래스에 대한 소스 파일도 만들어 주는데, 이 경우 LightSwitchCodeOnly.cpp 입니다. 기본적으로 소스 파일에는 기본적인 인클루드 구성이 들어 있습니다.

클래스 생성자를 추가하는 것으로 시작합니다.

    ALightSwitchCodeOnly::ALightSwitchCodeOnly()
    {

    }

LightSwitchCodeOnly 생성자에서 C++ 가 사용된 곳은:

  • Desired Brightness 변수의 값을 15 로 설정합니다.

    DesiredBrightness = 15.0f;
  • PointLightComponent 를 생성하고, 그 변수(와 그 밝기를 DesiredBrightness 로 설정하는 것까지 포함해서) 설정 후 루트 컴포넌트로 만듭니다.

    PointLight1 = CreateDefaultSubobject<UPointLightComponent>(TEXT("PointLight1"));
    PointLight1->Intensity = DesiredIntensity;
    PointLight1->bVisible = true;
    RootComponent = PointLight1;
  • SphereComponent 를 생성하고, 그 변수를 설정한 다음 PointLightComponent 에 붙입니다.

    Sphere1 = CreateDefaultSubobject<USphereComponent>(TEXT("Sphere1"));
    Sphere1->InitSphereRadius(250.0f);
    Sphere1->SetupAttachment(RootComponent);
  • Actor 가 SphereComponent 에 겹치거나 떨어지면 호출되는 델리게이트로 OnOverlap 함수를 지정합니다.

    Sphere1->OnComponentBeginOverlap.AddDynamic(this, &ALightSwitchCodeOnly::OnOverlapBegin);       // 이 컴포넌트가 무언가에 겹칠 때에 대한 알림 구성
    Sphere1->OnComponentEndOverlap.AddDynamic(this, &ALightSwitchCodeOnly::OnOverlapEnd);       // 이 컴포넌트가 무언가에 겹칠 때에 대한 알림 구성

소스 파일에서도 클래스에 대해 선언된 함수를 정의할 수 있습니다. 예를 들어 LightSwitchCodeOnly.cpp 에는 ToggleLight 를 호출하여 PointLightComponent 에 대한 표시여부 토글 동작을 하는 OnOverlapBeginOnOverlapEnd 구현이 있습니다. 클래스 생성자와 합친 소스 파일은 이렇습니다:

LightSwitchCodeOnly.cpp

// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.

#include "BasicClasses.h"
#include "LightSwitchCodeOnly.h"

ALightSwitchCodeOnly::ALightSwitchCodeOnly()
{
    DesiredIntensity = 3000.0f;

    PointLight1 = CreateDefaultSubobject<UPointLightComponent>(TEXT("PointLight1"));
    PointLight1->Intensity = DesiredIntensity;
    PointLight1->bVisible = true;
    RootComponent = PointLight1;

    Sphere1 = CreateDefaultSubobject<USphereComponent>(TEXT("Sphere1"));
    Sphere1->InitSphereRadius(250.0f);
    Sphere1->SetupAttachment(RootComponent);

    Sphere1->OnComponentBeginOverlap.AddDynamic(this, &ALightSwitchCodeOnly::OnOverlapBegin);       // 이 컴포넌트가 무언가에 겹칠 때에 대한 알림 구성
    Sphere1->OnComponentEndOverlap.AddDynamic(this, &ALightSwitchCodeOnly::OnOverlapEnd);       // 이 컴포넌트가 무언가에 겹칠 때에 대한 알림 구성

}

void ALightSwitchCodeOnly::OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
    if (OtherActor && (OtherActor != this) && OtherComp)
    {
        ToggleLight();
    }
}

void ALightSwitchCodeOnly::OnOverlapEnd(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
    if (OtherActor && (OtherActor != this) && OtherComp)
    {
        ToggleLight();
    }
}

void ALightSwitchCodeOnly::ToggleLight()
{
    PointLight1->ToggleVisibility();
}

BasicClasses.h 는 클래스가 구성되어 있는 프로젝트 이름을 참조합니다.

빈 프로젝트에 처음 코드 클래스를 추가한 경우, 언리얼 에디터를 닫고, Visual Studio 나 XCode 에서 프로젝트를 컴파일한 다음 언리얼 에디터를 열거나 프로젝트를 다시 열면 게임 모듈이 제대로 생성 및 로드됩니다. 또 Build Configuration (빌드 환경설정)이 프로젝트를 여는 데 사용한 언리얼 에디터 실행파일 버전에 일치하는지 확인하는 것도 중요합니다. 빌드 환경설정 및 프로젝트 컴파일 관련 상세 내용은 게임 프로젝트 컴파일하기 문서를 참고해 주시기 바랍니다.

기존 C++ 프로젝트에 코드를 추가한 경우, 핫 리로드 기능을 사용하여 언리얼 에디터 안에서 새로운 코드를 컴파일할 수 있습니다.

C++ 클래스는 C++ 클래스는 물론 블루프린트 클래스를 가지고도 확장 가능합니다 - C++ 클래스 마법사Show All Classes (모든 클래스 표시) 체크박스에 체크한 다음 블루프린트 클래스 생성 도중 부모 클래스 선택 창의 Custom Classes (커스텀 클래스) 섹션에 표시됩니다.

LightSwitchCodeOnly 클래스는 클래스 뷰어 에 있으며, 거기서 레벨에 끌어 놓을 수 있습니다. 클래스 뷰어 를 사용해서 레벨에 액터 배치 관련 상세 정보는 액터 배치하기 문서를 참고해 주시기 바랍니다.

Select Skin
Light
Dark

새로운 언리얼 엔진 4 문서 사이트에 오신 것을 환영합니다!

문서 사이트에 대한 의견을 모을 수 있는 피드백 시스템을 포함해서 여러가지 새로운 기능을 준비하고 있습니다. 아래 Documentation Feedback 포럼(영문) 또는 언리얼 엔진 네이버 공식 카페(한글) 중 편하신 곳에 의견이나 문제점을 알려 주세요.

새 시스템이 준비되면 알려 드리겠습니다.

네이버 카페
공식 포럼