슬레이트 에디터 창 퀵스타트 가이드

슬레이트를 사용해 간단한 에디터 창을 빌드합니다.

언리얼 엔진의 UI 프레임워크인 슬레이트(Slate) 를 사용해 사용자 입력에 반응하는 간단한 에디터 창을 생성하는 방법에 대한 단계별 가이드입니다. 이 페이지는 슬레이트가 다른 시스템들과 상호작용하는 방식에 대한 종합적인 가이드가 아닙니다. 그보다는 슬레이트의 구문과 UI의 레이아웃의 기본적인 연관성, 그리고 UI가 이벤트에 반응하게 만드는 기초적인 방법에 집중합니다.

1. 프로젝트 구성하기

이 가이드는 다음과 같이 설정된 SlateQuickstartGame 라는 새 프로젝트를 사용합니다.

  • 템플릿: 3인칭 프로젝트

  • C++ 프로젝트

기존 프로젝트를 사용해 이 가이드를 따를 수도 있습니다. 이 프로젝트는 에디터 기능에 집중하기 때문에 특정한 타깃 플랫폼에 의존하지 않습니다.

2. 창 플러그인 만들기

간단한 새 에디터 창을 만들려면 먼저 편집(Edit) > 플러그인(Plugins) 창을 연 후 + 추가(+ Add) 버튼을 눌러 새 플러그인을 생성합니다. 플러그인 유형으로 에디터 독립형 창(Editor Standalone Window) 을 선택하고 이름을 SlateQuickstartWindow 로 지정합니다. 플러그인 생성(Create Plugin) 을 클릭해 작업을 마칩니다.

이미지를 클릭하면 확대됩니다.

이 작업은 자동으로 기본 에디터 창을 지원하는 필수 C++ 클래스가 있는 플러그인 모듈을 생성합니다. 에디터를 닫고 프로젝트를 리컴파일한 후 다시 프로젝트를 엽니다. 창(Window) 드롭다운에서 새로운 에디터 창을 찾을 수 있습니다.

이미지를 클릭하면 확대됩니다.

이 창을 처음으로 확인할 때는 자리표시자 텍스트만 표시되고 인터랙티브 엘리먼트는 표시되지 않습니다.

창의 코드 이해하기

계속해서 메뉴를 빌드하기 전에, 슬레이트의 선언 구문 사용법을 빠르게 살펴보기 위해 SlateQuickstartWindowModule.cpp 의 코드를 검토해 보겠습니다. 슬레이트 코드는 OnSpawnPluginTab 함수에 포함되어 있습니다. 함수를 처음으로 보면 다음과 같은 모습입니다.

TSharedRef<SDockTab> FSlateQuickstartWindowModule::OnSpawnPluginTab(const FSpawnTabArgs& SpawnTabArgs)

{
    FText WidgetText = FText::Format(

        LOCTEXT("WindowWidgetText", "{1}의 {0}에 코드를 추가하여 이 창의 내용을 덮어씁니다."),
        FText::FromString(TEXT("FSlateQuickstartWindowModule::OnSpawnPluginTab")),
        FText::FromString(TEXT("SlateQuickstartWindow.cpp"))

        );

    return SNew(SDockTab)
    .TabRole(ETabRole::NomadTab)
    [
        // 탭 콘텐츠를 여기에 넣으세요!

        SNew(SBox)
        .HAlign(HAlign_Center)
        .VAlign(VAlign_Center)
        [
            SNew(STextBlock)
            .Text(WidgetText)
        ]
    ];

}

이 함수는 다음 단계를 수행합니다.

  1. FText::Format 으로 WidgetText 라는 스트링을 빌드해 여러 개의 스트링을 결합합니다.

  2. SNew 함수를 사용해 새로운 SDockTab 을 정의합니다. 이는 도킹 가능한 창을 나타냅니다.

  3. SDockTab 을 콘텐츠를 포함할 수 있는 SBox 엘리먼트로 채웁니다. 이 박스에는 창의 중앙에 정렬할 수 있는 HAlignVAlign 파라미터가 있습니다.

  4. SBox 에 새로운 STextBlock 을 추가하고 그 텍스트를 WidgetText 값에 설정합니다.

  5. 이러한 UI 엘리먼트를 모두 포함한 SDockTab 을 반환합니다.

이 작동 방법을 이해하는 가장 좋은 방법은 UMG에서 유사한 유저 인터페이스를 어떻게 생성하면 될지 생각해 보는 것입니다. 이러한 유저 인터페이스를 UMG에서 다시 구현하려면, 박스 위젯을 스테이지에 루트 UI 엘리먼트로 드래그한 후 그 안에 텍스트 위젯을 배치하고 중앙 정렬로 변경할 것입니다. 스테이지 및 계층구조는 다음 이미지와 비슷합니다.

이미지를 클릭하면 확대됩니다.

SlateQuickstartWindow 의 경우, 뷰포트 스테이지가 SDockTab 위젯으로 대체됩니다. 코드를 검토할 때는 대괄호로 주어진 위젯 내 중첩된 요소가 무엇인지 정의하고, 온점으로 디테일 패널에 보이는 파라미터 값을 설정합니다.

슬레이트의 선언 구문에 대한 자세한 정보는 슬레이트 개요를 참조하세요.

3. 메뉴 슬레이트 위젯 만들기

플러그인 마법사가 생성한 FSlateQuickstartWindowModule 클래스에 직접 슬레이트 위젯을 추가할 수 있습니다. 하지만 이때 위젯의 콜백 처리에 몇 가지 제한 사항이 있습니다. 따라서 메뉴의 콘텐츠를 포함할 전용 슬레이트 위젯을 만든 후 해당 위젯을 FSlateQuickstartWindowModule 클래스에 추가해야 합니다.

  1. 콘텐츠 드로어에서 C++ 클래스(C++ Classes) 폴더를 클릭한 후 우클릭하고 새로운 C++ 클래스(New C++ Class) 를 클릭합니다.

    이미지를 클릭하면 확대됩니다.

  2. C++ 클래스 추가(Add C++ Class) 창에서 슬레이트 위젯(Slate Widget) 을 선택한 후, 다음(Next) 을 클릭합니다.

  3. 새로운 C++ 클래스의 세팅을 다음과 같이 변경합니다.

    이미지를 클릭하면 확대됩니다.

    • 클래스 타입: Public

    • 이름: QuickStartWindowMenu

    • 모듈: SlateQuickstartWindow(에디터)

    클래스 생성(Create Class) 을 클릭해 작업을 마칩니다.

클래스 생성을 클릭하기 전에 모듈 드롭다운을 SlateQuickstartWindow 모듈에 설정해야 합니다. 그러면 플러그인의 코드에 클래스가 추가됩니다. 이 작업을 하지 않으면 마법사가 게임 코드에 클래스를 넣으며, 슬레이트 위젯이 플러그인에 표시되지 않습니다.

마법사는 플러그인의 Source 폴더에 SQuickStartWindowMenu 라는 새 C++ 클래스를 생성한 다음, 프로젝트의 Visual Studio 솔루션을 재생성합니다.

4. 위젯으로 메뉴 채우기

메뉴에 슬레이트 위젯을 추가하려면 SQuickStartWindowMenu.cpp 를 열고 Construct 함수에 슬레이트 위젯을 추가합니다. 처음에 이 함수를 볼 때는 다음과 같습니다.

    void SQuickStartWindowMenu::Construct(const FArguments& InArgs)
    {
        /*
        ChildSlot
        [
            // 위젯 채우기
        ];
        */
    }

창을 채우려면 다음 단계를 따르세요.

  1. Construct 함수에서 주석 처리된 코드를 삭제합니다.

  2. Construct 함수에 SNew 함수가 있는 새로운 SVerticalBox를 추가한 후 이어서 +SVerticalBox::Slot() 엘리먼트 2개를 추가합니다. 두 슬롯에 모두 .AutoHeight() 프로퍼티를 부여합니다.

    SNew(SVerticalBox)
    +SVerticalBox::Slot()
    .AutoHeight()
    [
    ]
    +SVerticalBox::Slot()
    .AutoHeight()
    [
    ]
  3. 첫 번째 세로 박스 슬롯 안에 2개의 슬롯이 있는 SHorizontalBox 를 추가합니다. 두 슬롯에 모두 .VAlign(VAlign_Top) 프로퍼티를 부여합니다.

    +SVerticalBox::Slot()
    [
        SNew(SHorizontalBox)
        +SHorizontalBox::Slot()
        .VAlign(VAlign_Top)
        [
        ]
        +SHorizontalBox::Slot()
        .VAlign(VAlign_Top)
        [
        ]
    ]

    이렇게 하면 세로 박스 안에 가로 박스를 중첩하여 이 첫 번째 슬롯을 2개의 열로 효율적으로 나눌 수 있습니다.

  4. 첫 번째 가로 슬롯에 새로운 STextBlock 위젯을 추가합니다. .TextFText::FromString("Test Button") 로 설정합니다.

    +SHorizontalBox::Slot()
    .VAlign(VAlign_Top)
    [
        SNew(STextBlock)
        .Text(FText::FromString("Test Button"))
    ]

사용자가 보게 될 텍스트를 표시할 때마다 FString 대신 현지화를 지원하는 FText 를 사용하거나 다른 텍스트 표시 방법을 사용해야 합니다. 자세한 정보는 텍스트 현지화를 참조하세요.

  1. 두 번째 가로 슬롯에 새로운 SButton 위젯을 추가합니다. .TextFText::FromString("Press Me") 로 설정합니다.

    +SHorizontalBox::Slot()
    .VAlign(VAlign_Top)
    [
        SNew(SButton)
        .Text(FText::FromString("Press Me"))
    
    ]
  2. 두 번째 세로 박스 슬롯 안에 2개의 슬롯이 있는 또 다른 가로 박스를 생성합니다. 첫 번째 가로 슬롯에 "Test Checkbox" 라는 STextBlock 위젯을 부여한 후, 두 번째 가로 슬롯에 SCheckBox 위젯을 추가합니다.

    +SVerticalBox::Slot()
    .AutoHeight()
    [
        SNew(SHorizontalBox)
        +SHorizontalBox::Slot()
        .VAlign(VAlign_Top)
        [
            SNew(STextBlock)
            .Text(FText::FromString("Test Checkbox"))
        ]
        +SHorizontalBox::Slot()
        .VAlign(VAlign_Top)
        [
            SNew(SCheckBox)
        ]
    ]
  3. 슬레이트 창의 전체 정의는 이제 다음과 같아야 합니다.

    return SNew(SDockTab)
    .TabRole(ETabRole::NomadTab)
    [
        SNew(SVerticalBox)
        +SVerticalBox::Slot()
        .AutoHeight()
        [
            SNew(SHorizontalBox)
            +SHorizontalBox::Slot()
            .VAlign(VAlign_Top)
            [
                SNew(STextBlock)
                .Text(FText::FromString("Test Button"))
            ]
            +SHorizontalBox::Slot()
            .VAlign(VAlign_Top)
            [
                SNew(SButton)
                .Text(FText::FromString("Press Me"))
            ]
        ]
        +SVerticalBox::Slot()
        .AutoHeight()
        [
            SNew(SHorizontalBox)
            +SHorizontalBox::Slot()
            .VAlign(VAlign_Top)
            [
                SNew(STextBlock)
                .Text(FText::FromString("Test Checkbox"))
            ]
            + SHorizontalBox::Slot()
            .VAlign(VAlign_Top)
            [
                SNew(SCheckBox)
            ]
        ]
    ];
  4. 코드를 저장하고 컴파일한 후 언리얼 에디터에서 프로젝트를 열고 창을 엽니다.

    라이브 코딩(Live Coding)이 활성화되고 프로젝트가 언리얼 에디터에서 열려 있는 동안에는 슬레이트 창을 컴파일할 수 없습니다. 코드를 컴파일하기 전에 언리얼 에디터를 종료해야 합니다.

    창을 열면 다음과 같아야 합니다.

    테스트 창의 프리뷰

    버튼이나 체크박스는 아직 아무것도 하지 않지만, 다음 섹션에서 기능을 추가할 수 있습니다.

5. 인터랙티브 위젯에 이벤트 바인딩

인터랙티브 슬레이트 위젯은 이벤트를 사용하여 클릭 또는 토글과 같은 인터랙션에 반응합니다. 이 섹션에서는 여러 개의 델리게이트를 생성해 이전 섹션의 체크 박스 및 버튼의 상호작용을 구동해 보겠습니다.

  1. SQuickStartWindowMenu.h 를 열고 다음 함수 및 변수를 선언합니다.

        public: 
        FReply OnTestButtonClicked();
        void OnTestCheckboxStateChanged(ECheckBoxState NewState);
        ECheckBoxState IsTestBoxChecked() const;
    
        protected:
        bool bIsTestBoxChecked;

    이러한 함수는 테스트 버튼 및 테스트 체크 박스를 클릭할 때 실행되는 로직을 포함하게 됩니다. 체크 박스는 IsTestBoxChecked 함수를 사용해 어떤 상태를 표시해야 할지 결정하며, bIsTestBoxChecked 가 해당 스테이트를 캐싱합니다.

  2. SQuickStartWindowMenu.cpp 에서 체크 박스 함수를 위해 다음을 구현합니다.

        void SQuickStartWindowMenu::OnTestCheckboxStateChanged(ECheckBoxState NewState)
        {
            bIsTestBoxChecked = NewState == ECheckBoxState::Checked ? true : false;
        }
    
        ECheckBoxState SQuickStartWindowMenu::IsTestBoxChecked() const
        {
            return bIsTestBoxChecked ? ECheckBoxState::Checked : ECheckBoxState::Unchecked;
        }

    이렇게 하면 체크 박스의 현재 상태에 게터 및 세터를 제공합니다. OnTestCheckboxStateChanged 함수는 사용자가 체크 박스의 상태를 어떻게 변경하는지에 따라 bIsTestBoxChecked 의 값을 설정합니다. 그동안 IsTestBoxChecked 함수가 해당 변수를 읽고 ECheckBoxState 로 다시 변환합니다.

  3. SCheckBox 위젯에 .OnCheckStateChanged 를 추가하고, FSlateQuickstartModule::OnTestCheckboxStateChanged 함수에 레퍼런스를 제공합니다. 그런 다음 IsChecked 파라미터를 추가하고,SQuickStartWindowMenu::IsTestBoxChecked 함수에 레퍼런스를 제공합니다.

        +SHorizontalBox::Slot()
        .VAlign(VAlign_Top)
        [
            SNew(SCheckBox)
            .OnCheckStateChanged(FOnCheckStateChanged::CreateSP(this, &SQuickStartWindowMenu::OnTestCheckboxStateChanged))
            .IsChecked(FIsChecked::CreateSP(this, &SQuickStartWindowMenu::IsTestBoxChecked))
        ]

    이제 사용자가 SCheckBox 위젯을 체크 및 체크 해제할 때를 트래킹할 수 있는 메커니즘이 생겼습니다.

  4. OnTestButtonClicked 함수에 대해 다음 구현을 생성합니다.

        FReply SQuickStartWindowMenu::OnTestButtonClicked()
        {
            UE_LOG(LogTemp, Warning, TEXT("Hello, world! The checkbox is %s."), (bIsTestBoxChecked ? TEXT("checked") : TEXT("unchecked")));
            return FReply::Handled();
        }

    이 함수는 체크 박스의 체크 여부를 표시하는 출력 로그에 짧은 메시지를 출력합니다.

  5. SButton.OnClicked 파라미터를 추가한 후 SQuickStartWindowMenu::OnTestButtonClicked 함수에 레퍼런스를 제공합니다.

        +SHorizontalBox::Slot()
        .VAlign(VAlign_Top)
        [
            SNew(SButton)
            .Text(FText::FromString("Press Me"))
            .OnClicked(FOnClicked::CreateSP(this, &SQuickStartWindowMenu::OnTestButtonClicked))
        ]

6. 창에 메뉴 추가하기

마지막으로, 생성한 슬레이트 위젯을 메뉴 탭의 코드에 추가해야 합니다.

  1. SlateQuickstartWindowModule.cpp 를 열고 SDockTab의 콘텐츠를 삭제합니다. 해당 코드는 이제 다음과 같아야 합니다.

    return SNew(SDockTab)
    .TabRole(ETabRole::NomadTab)
    [
    
    ];
  2. SDockTab 내에 SQuickStartWindowMenu 위젯을 추가합니다.

    return SNew(SDockTab)
    .TabRole(ETabRole::NomadTab)
    [
        SNew(SQuickStartWindowMenu)
    ];

코드를 저장하고 컴파일한 후 언리얼 에디터를 열어 창을 테스트합니다.

최종 결과

테스트 버튼을 클릭하면 콘솔 로그가 "Hello, world! The checkbox is unchecked."라는 메시지를 출력합니다. 체크 박스를 체크하면 "Hello, world! The checkbox is checked."라는 메시지를 출력합니다. 이는 슬레이트 창의 기본 작동 예시로, 커스텀 에디터 창을 생성해 확장할 수 있습니다.

직접 해보기

다양한 슬레이트 위젯 및 해당 슬레이트 위젯을 델리게이트에 바인딩하는 여러 가지 방법에 대한 예시는 STestSuite.cpp 를 참조하세요. 이 파일은 Source\Runtime\AppFramework\Private\Widgets\Testing 의 엔진 설치 디렉터리에서 찾을 수 있습니다. 이러한 위젯으로 실험하여 다양한 레이아웃 및 인터랙티브 엘리먼트를 생성할 수 있습니다. 또한 슬레이트 UI 엘리먼트로 실험하여 프로젝트 내 에셋 또는 데이터나 레벨 에디터의 월드와 상호작용하게 할 수도 있습니다.

태그
언리얼 엔진 문서의 미래를 함께 만들어주세요! 더 나은 서비스를 제공할 수 있도록 문서 사용에 대한 피드백을 주세요.
설문조사에 참여해 주세요
취소