언어:
페이지 정보
엔진 버전:
언리얼 엔진

유니티 개발자를 위한 언리얼 엔진 4

언리얼 엔진

image_0.png

이 글은 유니티 사용자 관점에서 보는 UE4 에 대한 개요로, 기존 유니티 경험을 UE4 월드로 옮겨오는 데 도움이 되었으면 합니다.

에디터

아래 그림은 유니티 에디터와 언리얼 에디터를 나란 놓은 것으로, 색을 통해 기능이 같은 부분을 확인할 수 있습니다. 각 블록에는 이름표를 붙여 그에 맞는 UE4 용어를 표시해 뒀습니다. 언리얼 에디터의 레이아웃은 드래그 앤 드롭을 통해 탭을 이리저리 끌어 붙여 입맛대로 조정하는 것이 가능합니다.

EditorCompare_Windows.png

EditorCompare_Mac.png

애셋 편집

유니티에서는 Inspector 탭을 사용하여 프로젝트에 선택된 애셋을 편집합니다. UE4 에서는 디테일 패널에 선택된 오브젝트의 프로퍼티가 노출되기는 하지만, 규모가 큰 편집 작업은 전용 창이나 탭 에서 이루어집니다. 웹 브라우저와 비슷하게 편집되는 애셋 각각에 대해 새로운 탭 창이 열립니다. 물론 각 탭은 자유롭게 끌어붙이거나 독립 창으로 띄울 수도 있습니다.

TabbedWindows_Windows.png

TabbedWindows_Mac.png

간략 용어집

아래 표의 왼쪽은 유니티에서 자주 쓰이는 용어와, 그 오른편은 상응하는 (또는 대략적으로 비슷한) UE4 용어입니다. UE4 키워드 링크를 통해 언리얼 엔진 온라인 문서의 상세 정보를 확인할 수 있습니다.

카테고리

유니티

UE4

게임플레이 유형

Component

Component

GameObject

Actor 액터, Pawn

Prefab

Blueprint Class 블루프린트 클래스

에디터 UI

Hierarchy Panel

World Outliner 월드 아웃라이너

Inspector

Details Panel 디테일 패널

Project Browser

Content Browser 콘텐츠 브라우저

Scene View

Viewport 뷰포트

메시

Mesh

Static Mesh 스태틱 메시

Skinned Mesh

Skeletal Mesh 스켈레탈 메시

머티리얼

Shader

Material 머티리얼, Material Editor 머티리얼 에디터

Material

Material Instance 머티리얼 인스턴스

이펙트

Particle Effect

Effect, Particle, Cascade 이펙트, 파티클, 캐스케이드

Shuriken

Cascade 캐스케이드

게임 UI

UI

UMG (Unreal Motion Graphics) 언리얼 모션 그래픽

애니메이션

Animation

Skeletal Animation System 스켈레탈 애니메이션 시스템

Mecanim

Persona 페르소나, Animation Blueprint 애니메이션 블루프린트

2D

Sprite Editor

Paper2D 페이퍼 2D

프로그래밍

C#

C++ C++

Script

Blueprint 블루프린트

피직스

Raycast

Line Trace, Shape Trace 라인 트레이스, 셰이프 트레이스

Rigid Body

Collision, Physics 콜리전, 피직스

런타임 플랫폼

iOS Player, Web Player

Platforms 플랫폼

프로젝트와 파일

이 디렉터리와 파일들은 전부 뭐죠?

유니티 프로젝트와 마찬가지로 언리얼 프로젝트는 항상 별도의 디렉터리에 존재하며 자체적인 프로젝트 파일을 갖습니다. .uproject 파일에 더블클릭 하면 게임을 언리얼 에디터에 로드할 수 있으며, 우클릭 으로 추가 옵션을 확인할 수도 있습니다. 프로젝트 폴더에는 게임의 콘텐츠와 소스는 물론 다양한 환경설정 파일과 바이너리가 들어있는 서브폴더가 들어있습니다. 가장 중요한 서브폴더는 ContentSource 입니다.

애셋은 어디에 넣지요?

UE4 에는 각 프로젝트마다 Content 폴더가 있습니다. 유니티 프로젝트의 Assets 폴더와 비슷하게 이 폴더에 게임 애셋이 저장됩니다. 애셋을 게임에 임포트하려면, 단순히 파일을 프로젝트의 Content 디렉터리에 끌어놓기만 하면 자동으로 임포트되어 콘텐츠 브라우저 에 나타납니다. 애셋도 외부 프로그램으로 파일을 변경할 때마다 자동으로 에디터에 업데이트됩니다.

ProjectOnDisk_Windows.png

ProjectOnDisk_Mac.png

주로 지원되는 파일 포맷은?

유니티는 다양한 파일 포맷을 지원합니다. UE4 는 가장 자주 쓰이는 파일 유형을 지원합니다:

애셋 유형

지원되는 포맷

3D

.fbx, .obj

텍스처

.png, .jpeg, .bmp ,.tga, .dds, .exr, .psd, .hdr

사운드

.wav

폰트

.ttf, .otf

비디오

.mov, .mp4, .wmv

씬은 어떻게 저장되나요?

유니티에서는 씬에 GameObject (게임오브젝트)를 배치하고 Scene (씬) 애셋 파일로 저장합니다. 언리얼에는 유니티의 Scene 과 비슷한 Map (맵) 파일이 있습니다. 맵 파일에는 레벨 과 그 안의 오브젝트에 대한 정보가 저장되며, 라이팅 데이터와 특정 레벨 전용 세팅도 포함됩니다.

프로젝트의 세팅은 어떻게 변경하나요?

모든 프로젝트 세팅은 메인 메뉴의 편집 / 프로젝트 세팅 아래에서 찾을 수 있습니다. 유니티의 프로젝트 세팅과 마찬가지로, 이를 통해 프로젝트 관련 (이름이나 아이콘 등의) 정보를 지정하고, 게임 입력 바인딩을 설정하고, 프로젝트 실행시의 엔진 작동 방식을 정의합니다. 각각의 프로젝트 세팅 관련 상세 정보는 여기서 확인하세요. 유니티에는 "플레이어 세팅" 이라는 것도 있습니다. 언리얼에서는 "플랫폼 세팅" 에 해당하는데, 프로젝트 세팅의 "플랫폼" 카테고리 아래에서 찾을 수 있습니다.

소스 파일은 어디로 가나요?

유니티에서는, 주로 C# 소스 파일을 애셋 폴더에 넣습니다.

UE4 는 다른 방식으로 작동합니다. C++ 코드가 있는 프로젝트의 경우, 프로젝트 디렉터리 아래 "Source" 서브폴더에는 C++ 소스 (.cpp), 헤더 (.h) 파일은 물론 빌드 (.Build.cs, .Target.cs) 파일 등 다양한 파일이 들어있습니다. 하지만 블루프린트 전용 프로젝트의 경우 Source 폴더가 없습니다.

UE4 에서 C++ 작업을 시작하는 가장 쉬운 방법은, 에디터의 (메인 파일 메뉴에 있는) 프로젝트에 코드 추가 를 사용하거나, 그냥 여러 템플릿 중 하나를 통해 처음부터 새로운 C++ 프로젝트를 만드는 것입니다. 콘텐츠 브라우저에서 바로 C++ 클래스를 찾아 그 아이콘을 더블클릭하면 Visual Studio 나 Xcode 에서 열 수 있습니다.

게임오브젝트에서 액터로

게임오브젝트는 어디있나요?

유니티에서 게임오브젝트는 월드에 배치할 수 있는 "사물"을 말합니다. UE4 에서 이것은 Actor 액터입니다. 언리얼 에디터에서는 배치 패널에서 뷰포트로 Empty Actor 공백 액터를 끌어놓으면 됩니다.

공백 액터만 가지고도 게임을 만들 수 있지만, UE4 에는 일정한 기능이 내장된 특수 액터 유형이 있습니다. 이를테면 (플레이어나 AI 오브젝트에 사용되는) Pawn 폰, (애니메이션 캐릭터에 사용되는) Character 캐릭터 등입니다. 공백 액터와 마찬가지로, 이러한 특수 액터 유형도 끌어놓은 다음 프로퍼티나 컴포넌트를 추가 또는 수정 가능합니다. 나중에 자세히 알아보겠지만, 지금은 UE4 에 이러한 특수 액터 작업을 위한 게임플레이 프레임워크 가 있다는 것만 기억해 두시면 됩니다.

UE4 의 액터는 유니티의 게임오브젝트와 약간 다릅니다. 유니티에서 GameObject 는 C# 클래스로 직접 확장할 수는 없습니다. UE4 에서 Actor 는 C++ 클래스로 상속을 통해 확장 및 수정 가능합니다. 이에 대해서는 나중에 자세히 알아보겠습니다!

컴포넌트는 어딨나요?

유니티에서는 게임오브젝트에 컴포넌트를 추가하여 함수성을 부여합니다.

UE4 에서는 액터에 컴포넌트를 추가합니다. 레벨에 공백 액터를 끌어놓은 이후에는, (디테일 패널의) 컴포넌트 추가 버튼을 클릭한 뒤 추가할 컴포넌트를 선택하면 됩니다. 여기서는 공백 액터를 끌어놓은 뒤, 베이스에 메시 컴포넌트를 추가하고, 라이트 소스에 이어 파티클 시스템을 붙여 화염을 만들어서 횃불을 만들고 있습니다.

유니티에서 게임오브젝트는 컴포넌트가 일반 목록으로 저장되지만, UE4 에서 액터에는 컴포넌트끼리 서로 붙는 계층구조 가 저장됩니다. 위 예제에서 확인할 수 있듯이, 라이트와 파티클이 메시에 붙어있습니다. 이는 중요한 내용을 암시하고 있는데, 나중에 복합 액터 및 게임오브젝트 에서 다루겠습니다.

유니티 프리팹에서 UE4 블루프린트 클래스로

유니티의 작업방식은 prefab 프리팹을 기반으로 합니다. 유니티에서는 컴포넌트로 게임오브젝트 세트를 만든 다음, 거기서 프리팹을 생성합니다. 그런 다음 프리팹 인스턴스를 월드에 배치하거나, 실행시간에 인스턴스를 생성합니다.

UE4 에서 그에 상응하는 작업방식은, Blueprint Class 블루프린트 클래스를 기반으로 합니다. UE4 에서는 컴포넌트로 액터를 만든 다음, 선택하고, (디테일 패널의) "블루프린트 / 스크립트 추가" 버튼을 클릭합니다. 그런 다음 블루프린트 클래스를 저장할 위치를 선택하고, "블루프린트 생성" 버튼을 눌러 새로운 블루프린트 클래스를 저장합니다!

새로운 블루프린트 클래스는 콘텐츠 브라우저 에서 찾을 수 있습니다. 더블클릭 해서 바로 편집할 수도 있고, 드래그 앤 드롭으로 레벨에 배치할 수도 있습니다.

스크립트 컴포넌트와 MonoBehaviour 는 어딨나요?

유니티에서는 게임오브젝트에 드롭하여 C# 스크립트를 추가하는 Script Component 스크립트 컴포넌트가 있습니다. MonoBehaviour 를 상속하는 클래스를 만들어서 컴포넌트가 하는 일을 정의하는 것이지요.

UE4 에도 비슷한 것이 있습니다. 완전히 새로운 Component 컴포넌트 클래스를 만든 다음 아무 액터에나 드롭할 수 있습니다. 블루프린트 스크립트 또는 C++ 어느 것을 사용해서든 컴포넌트 클래스를 만들 수 있습니다.

그러면 UE4 에서 컴포넌트 클래스는 어떻게 만들까요? 디테일 패널의 컴포넌트 추가 드롭다운에서, 새로운 컴포넌트를 생성하거나 기존의 것을 선택할 수 있습니다:

image alt text

유니티에서 새로운 MonoBehaviour 를 만들 때, Start() 함수와 Update() 함수가 있는 스켈레톤 클래스 파일이 주어집니다.

UE4 에서도 위의 Start / Update 함수와 비슷한 역할을 하는 InitializeComponent() 함수와 TickComponent() 함수가 있는 스켈레톤 클래스가 주어집니다.

블루프린트 스크립트 컴포넌트를 생성하면, 비주얼 노드로 동일한 함수가 주어집니다:

image alt text

스크립팅 가능 액터 블루프린트 클래스

UE4 의 멋진 기능이라면, 새로운 액터 블루프린트 클래스는 자체 블루프린트 비주얼 스크립트를 가질 수 있다는 점입니다! 이를 통해 개별 컴포넌트가 아닌 전체 오브젝트에 로직을 추가할 수 있습니다. (아래 설명하는) 상속 개념과 함께하면, 게임 디자인이 크게 유연해 집니다.

블루프린트 클래스가 비주얼 스크립트를 지원하는 것에 추가로, UE4 는 코드로 구현되는 C++ 클래스도 지원합니다. 양쪽에 놓고 보면 이렇습니다.

유니티 C#

UE4 C++

UE4 블루프린트

    using UnityEngine;
    using System.Collections;

    public class MyComponent : MonoBehaviour
    {
        int Count;

        // Use this for initialization.
        void Start ()
        {
            Count = 0;
        }

        // Update is called once per frame.
        void Update () 
        {

            Count = Count + 1;
            Debug.Log(Count);
        }
    }
    #pragma once
    #include "GameFramework/Actor.h"
    #include "MyActor.generated.h"

    UCLASS()
    class AMyActor : public AActor
    {
        GENERATED_BODY()
        int Count;

        // Sets default values for this actor's properties.
        AMyActor() 
        {
            // Allows Tick() to be called
            PrimaryActorTick.bCanEverTick = true;  
        }

        // Called when the game starts or when spawned.
        void BeginPlay()
        {
            Super::BeginPlay();
            Count = 0;
        }

        // Called every frame.
        void Tick(float DeltaSeconds)
        {
            Super::Tick(DeltaSeconds);
            Count = Count + 1;
            GLog->Log(FString::FromInt(Count));
        }
    };

UE4 블루프린트 클래스는 확장 가능

유니티 프리팹과 UE4 블루프린트 클래스는 게임에서 비슷하게 인스턴스 생성 가능합니다. 하지만 유니티는 한 프리팹을 다른 프리팹 안에 중첩시키는 경우 복잡해져서, 확장형 구성 요소로서의 역할이 제한됩니다.

UE4 에서는 블루프린트 클래스를 새로 만들고, 기존 블루프린트 클래스를 확장하여 새로운 프로퍼티, 컴포넌트, 비주얼 스크립트 함수성으로 살을 붙이는 것이 가능합니다.

예를 들어, UE4 에서 사람들을 쫓는다던가 하는 기본적인 괴물의 함수성을 구현하는 Monster 라는 이름의 블루프린트 클래스를 만듭니다. 그런 다음 이 블루프린트 클래스를 확장시킬 수 있는데, Dragon 으로 하여 불을 내뿜는 기능을 추가하고, Grue 라고 하여 밤이 되면 사람을 잡아먹는 기능을 추가하고, 이런 식으로 8 개 더 만들었다 칩시다. 이러한 Monster 의 서브클래스는 모두 Monster 의 기본적인 함수성을 상속하고, 그 위에 새로운 기능이 추가됩니다.

유니티에서는 이러한 구현을 하려면, Dragon 하나, Grue 하나 식으로 각기 다른 게임오브젝트 프리팹을 만들어야 할 것입니다. 여기서 모든 몬스터에 새로 만든 대화 컴포넌트를 사용하여 새로운 능력을 추가해야겠다 칩시다. 유니티에서는 새로운 함수성을 복사하여 10 개의 프리팹 모두 일일이 찾아 붙여넣어 줘야 합니다.

UE4 에서는 그냥 Monster 블루프린트 클래스를 편집하여 대화 능력을 추가해 주기만 하면 됩니다. 끝! Dragon, Grue, 나머지 8 종의 Monster 서브클래스 모두 자동으로 새로운 대화 함수성을 상속하므로, 일일이 건드릴 필요 없습니다.

하나 더! 지금까지 블루프린트 클래스에 대해 말씀드린 모든 것은 C++ 클래스에도 적용되며, 액터와 컴포넌트에도 마찬가지입니다. 이 시스템은 확장가능 함수성의 대규모 개발 지원을 위해 디자인된 것으로, 열 명의 개발자든 백 명의 개발자든 다양한 규모의 프로젝트를 모두 지원합니다.

블루프린트? C++? 아니면 둘 다?

블루프린트 비주얼 스크립트는 간단한 게임내 로직 흐름이나 액션 시퀀스에 이상적입니다. 디자이너, 아티스트, 비주얼 지향형 프로그래머에게 뛰어난 시스템인데, 게임내 오브젝트를 비주얼 방식으로 쉽게 접근하고 제어할 수 있기 때문입니다. 블루프린트만 가지고도 소규모 독립형 게임을 만들 수 있습니다. 태피 치킨만 봐도 확실히 알 수가 있습니다.

C++ 프로그래밍은 게임플레이 시스템, 복잡한 AI, 새로운 엔진 기능 제작같은 대규모 작업용입니다. C++ 경험이 이미 있으신 분이라면, 언리얼 엔진 프로그래밍 기본 문서를 참고하세요.

대부분의 프로젝트는 블루프린트와 C++ 를 혼합해 사용합니다. 여러 개발자들은 블루프린트를 사용하여 게임 함수성 프로토타입을 제작합니다. 쉽고 재밌기까지 하니까요. 그러다가 나중에 퍼포먼스와 엔지니어링 상의 이유로 그 일부 또는 전부를 C++ 로 옮기기도 합니다.

블루프린트 클래스는 C++ 클래스 확장가능

UE4 게임 개발의 마법같은 부분은 대부분 프로그래머가 C++ 로 신기능을 구현하고, 디자이너와 아티스트는 블루프린트로 그 덕을 보면서 추가적인 요구를 하는 협업을 통해 이루어집니다! UE4 기반 슈팅 게임에서 픽업을 구현할 때, 시스템 프로그래밍에는 C++ 클래스를 사용하고 작동방식과 외형에는 블루프린트 클래스를 혼합해서 사용하는 팀 구성 예제입니다:

image alt text

트랜스폼 컴포넌트

유니티에는 각 게임오브젝트마다 Transform 트랜스폼 컴포넌트가 있어, 게임오브젝트의 월드 내 위치, 회전, 스케일을 정해줍니다.

UE4 에도 비슷하게 액터에 Root 루트 컴포넌트가 있으며, Scene 씬 컴포넌트의 서브클래스가 될 수 있습니다. 씬 컴포넌트는 액터의 월드 내 위치, 회전, 스케일을 정해주며, 그 아래 모든 컴포넌트에 계층구조식으로 적용됩니다. 사용하게될 컴포넌트 다수는 씬 컴포넌트의 서브클래스로, 위치가 있으면 정말 편하기 때문입니다!

공백 액터를 배치했다 하더라도 UE4 는 그 액터에 대해 "디폴트 씬 루트"를 생성하는데, 이는 평이한 씬 컴포넌트입니다. 직접 새로운 씬 컴포넌트를 드롭하면, 디폴트 씬 루트가 대체됩니다.

복합 오브젝트

유니티에서는 게임오브젝트의 계층구조를 생성한 다음 그 트랜스폼을 같이 부모로 만들어 복합 오브젝트를 만듭니다:

image alt text

UE4 에서는 컴포넌트를 계층구조식으로 중첩시켜 복합 오브젝트를 만듭니다:

image alt text

도표에서 볼 수 있듯이, 중첩된 계층구조는 씬 컴포넌트끼리 붙여 만들 수 있는데, 트랜스폼이 있기 때문입니다. 유니티에서 트랜스폼 부모설정과 비슷한 개념이지요. 액터 컴포넌트(모든 컴포넌트의 베이스 클래스)는 액터 자신에게만 붙일 수 있습니다.

모든 것을 컴포넌트로 만드나요?

여러분 선택에 달린 일이지만, 대부분은 커스텀 컴포넌트 유형과 아울러 그 컴포넌트를 사용하는 액터 클래스를 조합해서 사용하게 될 것입니다. 앞서 말씀드린 바 있지만, UE4 에는 일정 수준의 능력을 보장하며 항상 특정 컴포넌트를 포함하는 특수 유형 액터가 여럿 있습니다. 예를 들어 Character 캐릭터에는 항상 Character Movement Component 캐릭터 무브먼트 컴포넌트가 포함됩니다.

엔진에서 종종 접할 수 있는 액터 서브클래스 유형은 여러가지 있으며, 거의 모든 유형의 게임에 유용하게 쓰입니다. 가장 흔히 쓰이는 내장 액터 목록은 이렇습니다:

  • Pawn 폰 - 제어가능한 게임 오브젝트, 전형적으로 플레이어의 아바타를 나타내는 액터 유형입니다. 폰은 Controller 컨트롤러 소유를 통해 플레이어나 AI 등에 의해 움직입니다.

  • Character 캐릭터 - 이족보행 아바타용으로 디자인된 보다 전문화된 버전의 폰으로, 그러한 게임 오브젝트 유형의 복잡도를 다수 처리합니다.

  • Controller 컨트롤러 - 폰을 Possess 빙의하여 제어합니다. 폰과 컨트롤러를 분리함으로써, 플레이어를 가정하고 그와 똑같은 인터페이스를 사용하여 폰을 임의로 조작하는 AI 컨트롤러 작성이 가능합니다.

  • Player Controller 플레이어 컨트롤러 - 플레이어의 게임패드, 터치, 마우스/키보드에서 입력을 받고, 그 입력을 사용하여 빙의중인 폰 또는 캐릭터를 구동시키기 위한 좀 더 전문화된 컨트롤러입니다.

즉 모든 것은 액터인가요?

모든 것이 그렇지는 않습니다. UE4 의 게임플레이에 가장 흔히 쓰이는 것이 액터 이고, World 월드에 Spawn 스폰 가능한 유일한 유형입니다. 즉 레벨에 배치하는 모든 것은 액터가 맞습니다.

또 한가지 알아둬야 할 중요한 유형은 Object 오브젝트입니다. 오브젝트는 사실 액터 외 다수를 포함해서 모든 언리얼 클래스의 기본 클래스입니다. 액터보다 훨씬 낮은 레벨에서의 구성이지만, reflection 리플렉션이나 serialization 시리얼라이제이션처럼 언리얼 클래스에서 기대하는 기능을 여전히 갖고 있습니다. 오브젝트는 액터 를 어찌해서는 맞지 않는 새로운 유형을 정의할 필요가 있을 때 사용하는 매우 기본적인 클래스입니다. 예를 들어 액터 컴포넌트 는 모든 컴포넌트의 베이스 클래스이며, 액터 가 아닌 오브젝트 에서 파생됩니다.

UE4 의 게임플레이 프레임워크 라는 것은 뭔가요?

자, 이제 약간 (많이 좋다는 의미의) 미쳐가기 시작하는 부분입니다. 게임 디자인을 시작할 수 있는 깔끔한 판을 제공한다는 점에서는 유니티나 언리얼이나 같습니다. 유니티에서는 기본적인 게임오브젝트와 컴포넌트로 모든 것을 만들 수 있고, 언리얼에서는 액터와 컴포넌트로 모든 것을 만들 수 있습니다.

하지만 언리얼쪽에는 게임플레이 프레임워크 라는 레이어가 한 층 더 있습니다. 유니티에는 전혀 없는 부분이지요. 언리얼에서도 반드시 사용할 필요는 없지만, 실제적으로 엄청 멋진 기능입니다! 사실, 엄청 기본적인 클래스 몇 개만 활용하면서 이미 확립된 규칙 몇 가지만 따르면 게임에 자동으로 (멀티플레이어 기능 완벽 지원 같은) 엄청난 기능이 추가되는데, 직접 구현이라도 할라치면 엄청나게 힘든 일이 될 것입니다.

이미 셀 수 없이 많은 뛰어난 게임이 언리얼의 게임플레이 프레임워크 기반으로 디자인되었기에, 작동 원리를 이해해 둘 가치는 충분합니다. 네, 이를 토대로 자신만의 버전을 운용할 수 있고, 원한다면 얼마든지 그렇게도 가능하니까요! 현재도 수백명의 뛰어난 언리얼 개발자들이 UE4 에서 이 프레임워크를 적극 활용하고 있으므로, 시간을 들여 배울 가치가 있습니다.

게임플레이 프레임워크를 사용하려면, 반드시 언리얼에 포함된 특수 내장 액터, 즉 , 캐릭터, 플레이어 컨트롤러 에 대해 배울 필요가 있으며, 궁극적으로 언리얼의 리플리케이션 및 네트워킹 기능의 작동 방식을 알아둬야 합니다. 지금은 일단 기본으로 돌아가 봅시다.

UE4 에서 코드 작성 방법

MonoDevelop 프로그래밍에 익숙한 분들

블루프린트 스크립트의 경우, 언리얼 에디터만 사용하면 됩니다. 모든것이 내장되어 있으니까요! C++ 코드를 작성하려면, Windows에서는 Visual Studio 무료 버전 또는 Mac에서는 Xcode 를 설치하면 됩니다. 새 프로젝트를 처음 생성( 또는 기존 프로젝트에 코드를 추가)할 때, UE4 가 자동으로 Visual Studio 프로젝트 파일을 생성 해 줍니다. 콘텐츠 브라우저 에서 C++ 클래스에 더블클릭 하거나, 메인 파일 메뉴의 "Visual Studio 열기"를 클릭하면 Visual Studio 가 열립니다.

image alt text

UE4 의 한 가지 중요한 차이점이라면, 가끔은 Visual Studio 프로젝트 파일 을 수동으로 새로고침 해줘야 한다는 것입니다 (예를 들면 UE4 새 버전을 다운로드한 후, 또는 디스크의 소스 파일을 수동으로 변경한 후). 메인 메뉴의 "Refresh Visual Studio Project" 또는 프로젝트 디렉터리에 있는 .uproject 파일에 우클릭 한 다음 "Generate Visual Studio project files" 를 선택하면 됩니다.

image alt text

이벤트 함수 작성 (Start, Update, 등)

MonoBehaviours 작업에 익숙하신 경우, Start, Update, OnDestroy 와 같은 메서드가 익숙하실 것입니다. 유니티 비헤이비어와 UE4 액터 및 컴포넌트 대응부분에 대한 비교는 이렇습니다.

유니티에서는, 이와 같은 단순한 컴포넌트가 있을 수 있습니다:

public class MyComponent : MonoBehaviour
{
    void Start() {}
    void OnDestroy() {}
    void Update() {}
}

하지만 기억할 것은, UE4 에서는 새로운 컴포넌트 유형에 대한 코딩만이 아닌 액터 자체에 바로 코드를 작성할 수 있습니다. 사실 매우 자주 쓰이는 유용한 기능입니다.

유니티의 Start, OnDestroy, Update 함수와 비슷하게, UE4 의 액터에도 비슷한 메서드 세트가 있습니다:

C++ :

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

    // 게임 시작시 호출됩니다.
    void BeginPlay();

    // 소멸시 호출됩니다.
    void EndPlay(const EEndPlayReason::Type EndPlayReason);

    // 매 프레임 이 액터 업데이트를 위해 호출됩니다.
    void Tick(float DeltaSeconds);
};

블루프린트 :

image_29.png

UE4 의 컴포넌트에는 다양한 함수가 들어있습니다. 간단한 예제입니다:

C++ :

UCLASS()
class UMyComponent : public UActorComponent
{
    GENERATED_BODY()

    // 소유중인 액터 생성 이후 호출됩니다
    void InitializeComponent();

    // 컴포넌트 또는 소유중인 액터가 소멸중일 때 호출됩니다.
    void UninitializeComponent();

    // 틱의 컴포넌트 버전입니다
    void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction);
};

블루프린트 :

image_30.png

기억하실 것은, UE4 에서는 부모 클래스 버전 메서드 호출이 중요합니다.

예를 들어 유니티 C# 에서는 base.Update() 가 되지만, UE4 C++ 에서는 Super::TickComponent() 를 사용합니다:

void UMyComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
    // 여기에 커스텀 틱 관련
    Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
}

C++ 에서 어떤 것은 "A" 로, 어떤 것은 "U" 로 시작하는 것을 눈치채셨을 것입니다. 접두사 "A" 는 Actor 의 서브클래스임을 나타내는 반면, 접두사 "U" 는 Object 의 서브클래스임을 나타냅니다. 다른 접두사도 있습니다. 예를 들어 "F" 는 대부분의 일반 데이터 구조체 또는 UObject 이외의 클래스에 사용됩니다.

UE4 에서 게임플레이 코드 작성

자, 이제부터 약간 깊이 들어가기 시작합니다. 게임 제작에 있어 매우 중요한 프로그래밍 주제에 대해 이야기해 보겠습니다. 유니티 C# 사용자가 언리얼 C++ 를 학습한다는 전제하에 설명을 하고 있지만, 사실 블루프린트 스크립트로도 원하는 거의 모든 것을 할 수 있기 때문입니다. 가급적이면 C++ 와 블루프린트 양쪽의 예제를 추가해 뒀습니다.

가장 흔한 게임플레이 프로그래밍 패턴과 언리얼에서 어떻게 접근할 것인지에 대해 조금 이야기해 봅시다. 유니티의 함수 중 다수는 언리얼에도 비슷해 보이는 비교가능 함수가 있습니다. 가장 자주 쓰이는 함수부터 하나씩 살펴보도록 하겠습니다.

게임오브젝트 인스턴스 생성 (Instantiate) / 액터 스폰

유니티에서는 Instantiate 함수를 사용하여 오브젝트의 인스턴스를 새로 만듭니다.

이 함수는 UnityEngine.Object 유형 (GameObject, MonoBehaviour, 등)을 받아 사본을 만듭니다.

public GameObject EnemyPrefab;
public Vector3 SpawnPosition;
public Quaternion SpawnRotation;

void Start()
{
    GameObject NewGO = (GameObject)Instantiate(EnemyPrefab, SpawnPosition, SpawnRotation);
    NewGO.name = "MyNewGameObject";
}

UE4 에서는 오브젝트의 인스턴스를 만드는 함수가 둘 정도 있는데, 필요에 따라 다릅니다. NewObject 는 새로운 UObject 유형을 만들 때, SpawnActor 는 AActor 유형을 스폰시킬 때 입니다.

먼저 UObject 와 NewObject 에 대해 간단히 얘기해 보겠습니다. 언리얼에서 UObject 의 서브클래스를 만드는 것은 유니티에서 ScriptableObject 의 서브클래스를 만드는 것과 매우 비슷합니다. 월드에 스폰시킬 필요가 없거나 액터처럼 컴포넌트를 붙일 필요가 없는 게임플레이 클래스에 좋습니다.

유니티에서, ScriptableObject 의 자체 서브클래스를 생성한다면, 이런 식으로 인스턴스를 만들 것입니다:

MyScriptableObject NewSO = ScriptableObject.CreateInstance<MyScriptableObject>();

그리고 언리얼에서, UObject 파생 유형을 만든다면, 이런 식으로 인스턴스를 만들 것입니다:

UMyObject* NewObj = NewObject<UMyObject>();

액터는 어떨까요? 액터는 SpawnActor 메서드를 사용해서 월드(C++ 의 UWorld) 오브젝트에 스폰됩니다. 월드 오브젝트는 어떻게 구할까요? 일부 UObject 에서는 GetWorld 오브젝트 메서드를 제공해 줍니다. 예를 들어 모든 액터가 그렇지요.

다른 액터를 전달하는 대신, 스폰하고자 하는 액터의 "클래스" 를 전달하는 것이 보일 것입니다. 우리 예제에서 클래스는 AMyEnemy 의 서브클래스가 될 수 있습니다.

하지만 다른 오브젝트의 "사본" 을 만들고자 한다면? Instantiate 로 가능한 것처럼 말이지요?

NewObject 와 SpawnActor 함수에도 작업할 "템플릿" 오브젝트를 줄 수 있습니다. 그러면 언리얼은 "처음서부터" 오브젝트를 새로 만드는 것이 아니라, 그 오브젝트의 사본을 만듭니다. 그 UPROPERTY 와 컴포넌트를 모두 복사해 옵니다.

AMyActor* CreateCloneOfMyActor(AMyActor* ExistingActor, FVector SpawnLocation, FRotator SpawnRotation)
{
    UWorld* World = ExistingActor->GetWorld();
    FActorSpawnParameters SpawnParams;
    SpawnParams.Template = ExistingActor;
    World->SpawnActor<AMyActor>(ExistingActor->GetClass(), SpawnLocation, SpawnRotation, SpawnParams);
}

위의 "처음서부터" 라는 것이 무슨 뜻인지 의아해 할 수가 있습니다. 생성하는 각 오브젝트 클래스마다 그 프로퍼티와 컴포넌트의 기본값이 들어있는 기본 템플릿이 있습니다. 이 프로퍼티를 덮어쓰지 않고 별도의 템플릿을 제공해주지 않는다면, 언리얼은 이러한 기본값을 사용하여 오브젝트를 생성합니다. 이에 대한 이해를 돕기 위해, 먼저 MonoBehaviour 를 예로 살펴봅시다:

public class MyComponent : MonoBehaviour
{
    public int MyIntProp = 42;
    public SphereCollider MyCollisionComp = null;

    void Start()
    {
        // 콜리전 컴포넌트가 없는 경우 생성합니다
        if (MyCollisionComp == null)
        {
            MyCollisionComp = gameObject.AddComponent<SphereCollider>();
            MyCollisionComp.center = Vector3.zero;
            MyCollisionComp.radius = 20.0f;
        }
    }
}

위 예제에서, 기본값이 42 인 int 프로퍼티가 있으며, 기본 반경이 20 인 SphereCollider 컴포넌트가 있습니다.

오브젝트의 생성자를 사용하여 언리얼에서도 똑같은 작업이 가능합니다.

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

    UPROPERTY()
    int32 MyIntProp;

    UPROPERTY()
    USphereComponent* MyCollisionComp;

    AMyActor()
    {
        MyIntProp = 42;

        MyCollisionComp = CreateDefaultSubobject<USphereComponent>(FName(TEXT("CollisionComponent"));
        MyCollisionComp->RelativeLocation = FVector::ZeroVector;
        MyCollisionComp->SphereRadius = 20.0f;
    }
};

AMyActor 생성자에서 클래스의 기본 프로퍼티 값을 설정해 줬습니다. CreateDefaultSubobject 함수가 사용된 부분을 보세요. 이를 통해 컴포넌트를 생성한 뒤 기본 프로퍼티를 할당할 수 있습니다. 이 함수를 사용하여 만드는 서브오브젝트는 전부 기본 템플릿처럼 작동하므로, 서브클래스나 블루프린트에서 변경할 수 있습니다.

한 유형에서 다른 유형으로 형변환(Cast)

여기서는 이미 있는 것으로 알고있는 컴포넌트를 구한 다음 특정 유형으로 형변환(cast)한 뒤 조건에 따라 어떤 작업을 하겠습니다.

유니티 C#:

Collider collider = gameObject.GetComponent<Collider>;
SphereCollider sphereCollider = collider as SphereCollider;
if (sphereCollider != null)
{
        // ...
}

UE4 C++:

UPrimitiveComponent* Primitive = MyActor->GetComponentByClass(UPrimitiveComponent::StaticClass());
USphereComponent* SphereCollider = Cast<USphereComponent>(Primitive);
if (SphereCollider != nullptr)
{
        // ...
}

게임오브젝트 / 액터 소멸(Destroy)

유니티

C++

블루프린트

    Destroy(MyGameObject);
    MyActor->Destroy();

image_23.png

게임오브젝트 / 액터 소멸 (1초 딜레이)

유니티

C++

블루프린트

    Destroy(MyGameObject, 1);
    MyActor->SetLifeSpan(1);

클릭하면 원래 크기로 봅니다.

게임오브젝트 / 액터 비활성화

유니티

C++

블루프린트

    MyGameObject.SetActive(false);
    // Hides visible components
    MyActor->SetActorHiddenInGame(true);

    // Disables collision components
    MyActor->SetActorEnableCollision(false);

    // Stops the Actor from ticking
    MyActor->SetActorTickEnabled(false);

클릭하면 원래 크기로 봅니다.

컴포넌트에서 게임오브젝트 / 액터 접근

유니티

C++

블루프린트

    GameObject ParentGO = 
    MyComponent.gameObject; 
     AActor* ParentActor = 
     MyComponent->GetOwner();

클릭하면 원래 크기로 봅니다.

게임오브젝트 / 액터에서 컴포넌트 접근

유니티

MyComponent MyComp = gameObject.GetComponent<MyComponent>();

C++

UMyComponent* MyComp = MyActor->FindComponentByClass<UMyComponent>();

블루프린트

image_33.png

게임오브젝트 / 액터 찾기

// 이름으로 게임오브젝트 찾기
GameObject MyGO = GameObject.Find("MyNamedGameObject");

// 유형으로 오브젝트 찾기
MyComponent[] Components = Object.FindObjectsOfType(typeof(MyComponent)) as MyComponent[];
foreach (MyComponent Component in Components)
{
        // ...
}

// 태그로 게임오브젝트 찾기
GameObject[] GameObjects = GameObject.FindGameObjectsWithTag("MyTag");
foreach (GameObject GO in GameObjects)
{
        // ...
}

// 이름으로 액터 찾기 (UObject 에도 작동)
AActor* MyActor = FindObject<AActor>(nullptr, TEXT("MyNamedActor"));

// 유형으로 액터 찾기 (UWorld 오브젝트 필요)
for (TActorIterator<AMyActor> It(GetWorld()); It; ++It)
{
        AMyActor* MyActor = *It;
        // ...
}

image alt text

// 유형으로 UObject 찾기
for (TObjectIterator<UMyObject> It; It; ++it)
{
    UMyObject* MyObject = *It;
    // ...
}

// 태그로 액터 찾기 (ActorComponent 에도 작동, 대신 TObjectIterator 사용)
for (TActorIterator<AActor> It(GetWorld()); It; ++It)
{
    AActor* Actor = *It;
    if (Actor->ActorHasTag(FName(TEXT("Mytag"))))
    {
        // ...
    }
}

image alt text

게임오브젝트 / 액터에 태그 추가

MyGameObject.tag = "MyTag";

// 액터는 태그를 여럿 가질 수 있습니다
MyActor.Tags.AddUnique(TEXT("MyTag"));

image alt text

모노비헤이비어 / 액터컴포넌트 에 태그 추가

// 붙어있는 게임오브젝트의 태그를 변경합니다
MyComponent.tag = "MyTag";

// 컴포넌트에는 자체 태그 배열이 있습니다
MyComponent.ComponentTags.AddUnique(TEXT("MyTag"));

게임오브젝트 / 액터 및 모노비헤이비어 / 액터컴포넌트의 태그 비교

if (MyGameObject.CompareTag("MyTag"))
{
    // ...
}

// 붙어있는 게임오브젝트의 태그 검사
if (MyComponent.CompareTag("MyTag"))
{
    // ...
}

// 액터에 이 태그가 있는지 검사
if (MyActor->ActorHasTag(FName(TEXT("MyTag"))))
{
    // ...
}

image alt text

// 액터 컴포넌트에 이 태그가 있는지 검사
if (MyComponent->ComponentHasTag(FName(TEXT("MyTag"))))
{
    // ...
}

image alt text

피직스: 리짓바디 대 프리미티브 컴포넌트

유니티에서는 게임오브젝트에 물리 특성을 부여하기 위해 먼저 RigidBody 리짓바디 컴포넌트를 줍니다. 언리얼에서는 어떤 프리미티브 컴포넌트(C++ 의 UPrimitiveComponent)도 물리 오브젝트가 될 수 있습니다. 자주 쓰이는 프리미티브 컴포넌트라면 (캡슐, 구체, 박스 등의) ShapeComponent 셰이프 컴포넌트, StaticMeshComponent 스태틱 메시 컴포넌트, SkeletalMeshComponent 스켈레탈 메시 컴포넌트가 있습니다.

콜리전(충돌)과 시각적인 부분을 담당하는 것을 별도의 컴포넌트로 나눈 유니티와 달리, 언리얼은 물리적 가능성과 시각적인 가능성 개념이 프리미티브 컴포넌트에 결합되어 있습니다. 월드에 지오메트리를 가질 수 있는 컴포넌트라면, 프리미티브 컴포넌트의 물리적인 서브클래싱을 통해 상호작용 또는 렌더링 가능한 것입니다.

레이어 대 채널

유니티에서는 "Layer" 레이어라 불립니다. UE4 에서는 Collision Channel 콜리전 채널을 사용하며, 비슷한 방식으로 작동합니다. 자세한 내용은 여기서 참고하세요.

레이캐스트 대 레이트레이스

유니티 C#:

GameObject FindGOCameraIsLookingAt()
{
    Vector3 Start = Camera.main.transform.position;
    Vector3 Direction = Camera.main.transform.forward;
    float Distance = 100.0f;
    int LayerBitMask = 1 << LayerMask.NameToLayer("Pawn");

    RaycastHit Hit;
    bool bHit = Physics.Raycast(Start, Direction, out Hit, Distance, LayerBitMask);

    if (bHit)
    {
        return Hit.collider.gameObject;
    }

    return null;
}

UE4 C++:

APawn* AMyPlayerController::FindPawnCameraIsLookingAt()
{
    // 이것으로 트레이스 관련 다양한 프로퍼티 수정이 가능합니다
    FCollisionQueryParams Params;
    // 플레이어의 폰을 무시합니다
    Params.AddIgnoredActor(GetPawn());

    // 히트 결과가 라인 트레이스로 채워집니다
    FHitResult Hit;

    // 카메라에서 레이캐스트를 하며, 폰하고만 충돌합니다 (ECC_Pawn 콜리전 채널에 있습니다)
    FVector Start = PlayerCameraManager->GetCameraLocation();
    FVector End = Start + (PlayerCameraManager->GetCameraRotation().Vector() * 1000.0f);
    bool bHit = GetWorld()->LineTraceSingle(Hit, Start, End, ECC_Pawn, Params);

    if (bHit)
    {
        // Hit.Actor 에는 트레이스에 걸린 액터로의 약 포인터가 저장됩니다
        return Cast<APawn>(Hit.Actor.Get());
    }

    return nullptr;
}

UE4 Blueprint:

클릭하면 원래 크기로 봅니다.

트리거

유니티 C#:

public class MyComponent : MonoBehaviour
{
    void Start()
    {
        collider.isTrigger = true;
    }
    void OnTriggerEnter(Collider Other)
    {
        // ...
    }
    void OnTriggerExit(Collider Other)
    {
        // ...
    }
}

UE4 C++:

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

    // 내 트리거 컴포넌트
    UPROPERTY()
    UPrimitiveComponent* Trigger;

    AMyActor()
    {
        Trigger = CreateDefaultSubobject<USphereComponent>(TEXT("TriggerCollider"));

        // 두 콜라이더 모두 이 옵션이 true 여야 이벤트가 발동됩니다
        Trigger.bGenerateOverlapEvents = true;

        // 콜라이더에 대한 콜리전 모드를 설정합니다
        // 이 모드는 레이캐스트, 스윕, 오버랩에 대한 콜라이더만 활성화시킵니다
        Trigger.SetCollisionEnabled(ECollisionEnabled::QueryOnly);
    }

    virtual void NotifyActorBeginOverlap(AActor* Other) override;

    virtual void NotifyActorEndOverlap(AActor* Other) override;
};

UE4 블루프린트:

image alt text

콜리전 반응 구성 관련 상세 정보는 여기서 참고하세요.

키니마틱 리짓바디

유니티 C#:

public class MyComponent : MonoBehaviour
{
    void Start()
    {
        rigidbody.isKinimatic = true;
        rigidbody.velocity = transform.forward * 10.0f;
    }
}

UE4 에서 콜리전 컴포넌트와 리짓바디 컴포넌트는 하나입니다. 그 베이스 클래스는 UPrimitiveComponent 로, 필요에 따라 여러가지 서브클래스가 있습니다 (USphereComponent, UCapsuleComponent, 등).

UE4 C++:

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

    UPROPERTY()
    UPrimitiveComponent* PhysicalComp;

    AMyActor()
    {
        PhysicalComp = CreateDefaultSubobject<USphereComponent>(TEXT("CollisionAndPhysics"));
        PhysicalComp->SetSimulatePhysics(false);
        PhysicalComp->SetPhysicsLinearVelocity(GetActorRotation().Vector() * 100.0f);
    }
};

입력 이벤트

유니티 C#:

public class MyPlayerController : MonoBehaviour
{
    void Update()
    {
        if (Input.GetButtonDown("Fire"))
        {
            // ...
        }
        float Horiz = Input.GetAxis("Horizontal");
        float Vert = Input.GetAxis("Vertical");
        // ...
    }
}

UE4 C++:

UCLASS()
class AMyPlayerController : public APlayerController
{
    GENERATED_BODY()

    void SetupInputComponent()
    {
        Super::SetupInputComponent();

        InputComponent->BindAction("Fire", IE_Pressed, this, &AMyPlayerController::HandleFireInputEvent);
        InputComponent->BindAxis("Horizontal", this, &AMyPlayerController::HandleHorizontalAxisInputEvent);
        InputComponent->BindAxis("Vertical", this, &AMyPlayerController::HandleVerticalAxisInputEvent);
    }

    void HandleFireInputEvent();
    void HandleHorizontalAxisInputEvent(float Value);
    void HandleVerticalAxisInputEvent(float Value);
};

UE4 블루프린트:

image alt text

프로젝트 세팅에서 입력 프로퍼티는 이런 모습입니다:

image alt text

입력 구성 관련 상세 정보는 여기서 확인할 수 있습니다.

잦은 질문

전 프로젝트를 자동으로 로드하는 방법은?

유니티의 지난 번 작업하던 프로젝트가 자동 로드되는 기능은, UE4 에서도 가능합니다. 프로젝트를 열 때 "Always load last project on Startup" (시작시 항상 지난 프로젝트를 로드합니다.) 옵션을 체크하면 됩니다. 언제든지 메인 메뉴의 Edit/Editor Preferences/Loading and Saving/Startup (편집/에디터 개인설정/로드 & 저장/Startup) 에서 설정을 바꿀 수 있습니다.

게임의 입력 바인딩 설정은 어디서 하나요?

유니티에서 프로젝트에 대한 인풋 매니저 세팅을 사용하여 기본 바인딩 구성을 했습니다. UE4 에서도 비슷합니다. 프로젝트 세팅을 연 다음 입력 카테고리를 설정합니다. 거기서 다양한 버튼 (액션) 및 아날로그 컨트롤 (축) 추가가 가능합니다. 각 컨트롤에 이름과 기본 바인딩을 설정합니다. 그런 다음 그 입력 이벤트가 트리거되면 게임의 폰에 대한 콜백을 구할 수 있습니다. 자세한 내용은 입력 문서 를 참고하세요.

프로젝트의 시작 씬은 어떻게 바꾸나요?

프로젝트의 스타트업 맵은 프로젝트 세팅 탭에서 바꿀 수 있습니다. 메인 메뉴에서 Edit/Project Settings->Maps & Modes (편집/프로젝트 세팅/맵 & 모드) 에서 스타트업 맵을 바꿀 수 있습니다.

게임 실행은 어떻게 하나요?

게임을 실행하는 가장 쉬운 방법은 메인 에디터 툴바의 "플레이" 버튼을 클릭하면 에디터 프로세스 안에서 게임이 바로 실행됩니다. 독립형 어플리케이션으로 실행하고자 하는 경우, "플레이" 옆의 드롭다운 화살표를 클릭한 다음 "독립형 게임"을 선택하면 됩니다. 마지막으로 모바일 디바이스나 웹 브라우저에서 실행시키고자 하는 경우, (해당 플랫폼에 미리 필요한 것을 설치한 이후) 툴바의 "실행" 버튼을 사용하면 됩니다.

유닛의 단위는 어떻게 되나요?

유니티에서 주로 1 유닛은 1 미터입니다. UE4 에서 주로 1 유닛은 1 센티미터 입니다.

즉 유니티에서 1 유닛(미터) 옮기면, UE4 에서 100 유닛(센티미터) 옮기는 것입니다.

유니티에서 2 피트를 옮기는 경우 0.61 유닛(미터)이며, UE4 에서는 61 유닛(센티미터) 입니다.

좌표계는 어떻게 되나요? 어디가 위쪽이죠?

유니티와 UE4 둘 다 왼손 좌표계를 사용합니다만, 축은 뒤집어져 있습니다. UE4 에서는 양수 X 가 "앞쪽", 양수 Y 가 "오른쪽", 양수 Z 가 "윗쪽"입니다. 이 부분은 바꿀 수 없으므로, 익숙해 져야 합니다.

게임에서 로그 출력을 어떻게 확인하나요?

UE4 에디터에서 "Output Log" 출력 로그창은 "Window -> Developer Tools" 창 -> 개발자 툴 메뉴에서 열 수 있습니다. 게임에 "-log" 명령줄 파라미터를 붙여 실행하면 게임 옆에 전용 로그 창이 뜨는데, 정말 유용합니다!

로그 출력 말인데, Debug.Log 는 어디있나요?

UE4 의 로그는 입맛대로 바꿀 수 있는 부분이 많습니다. 메시지 로깅 관련 상세 내용은 여기서(영문) 확인 가능합니다.

예외 처리는 어떻게 하나요?

유니티에서는 무언가 잘못되었을 때의 예외 처리(throwing exception)에 익숙할 것입니다. UE4 에서는 예외 처리를 사용하지 않습니다. 대신 'check()' 함수를 사용하여 치명적인 어서트 오류를 발동시킵니다. 오류 메시지를 전달할 수 있습니다. 오류 보고는 하되 프로그램을 멈추고 싶지는 않은 경우, 'ensure()' 를 대신 사용합니다. 전체 콜 스택 포함 오류 기록은 하되, 프로그램 실행은 계속합니다. 디버거가 붙어있는 경우, 두 함수 모두 디버거로 들어갑니다.

.NET 프레임워크는 어디있나요?

유니티와는 다르게 UE4 는 .NET 프레임워크를 사용하지 않습니다. UE4 는 별도의 컨테이너 클래스와 라이브러리가 있습니다. 주요 컨테이너를 비교해 보면 이렇습니다:

.Net 프레임워크

UE4

String

FString , FText

List

TArray

Dictionary

TMap

HashSet

TSet

다른 UE4 컨테이너 관련 상세 정보는 여기서(영문) 찾아볼 수 있습니다.

언리얼은 코드 변경사항을 자동으로 로드하나요?

네! 코드를 작성하면서 에디터를 열어둬도 됩니다. 코드 편집을 마친 다음 Visual Studio 에서 컴파일을 실행시키기만 하면, 에디터가 변경사항을 자동으로 "핫 리로드" 합니다. 에디터 메인 툴바의 컴파일 버튼을 클릭해도 됩니다. Visual Studio 디버거가 붙어있는 경우 유용하게 쓸 수 있습니다.

이제 어디로?

긴 글 읽어주셔서 감사합니다! 이 글은 세계 각지 언리얼 개발자들의 도움으로 언리얼 커뮤니티를 위해 작성된 것이며, 피드백이나 고칠 부분 알려주시면 대단히 감사하겠습니다. UE4 로 전환할 때 큰 도움이 되는 부분이 어떤 것이 있는가 배워가면서 이 문서를 계속 발전시키도록 하겠습니다!

이외에도 UE4 학습 자료가 많이 있습니다!