해당 글은 공부를 하면서 적은 글이기 때문에 틀릴 수 있습니다. 참고용으로만 봐주세요~
0. 개요
게임 프로그래머로 취업뿐 아니라 게임잼, 게임 동아리 및 UNSEEN과 같은 외부 활동에 참여할때 자체엔진 공부만으로는 어려움이 있었습니다.
취업은 아무래도 아직 CS나 자료구조, 알고리즘이 부족한게 발목을 많이 잡았던 것 같았습니다. 이전에 공부해온 DirectX, WinAPI, C++을 이용해 자체엔진을 만든 경험은 충분한 강점은 있다고 생각합니다. 그래픽스 파이프라인이라던지, 여러 디자인 패턴, 자료구조 등을 사용했기 때문에 상용엔진만 공부한 것 보다 엔진을 사용하는데 있어서 보다 깊이 있게 사용할 수 있다는 강점이 있다 생각합니다.
(물론 개인적인 생각이고 이런 기초적인 부분도 추가로 더 공부해서 확실한 강점이 되도록 만들어야겠다는 생각도 드네요.)
하지만 상용엔진을 사용해본 경험이 없어서 이러한 강점을 살리지 못한게 아쉬웠습니다.
게임잼이나 게임 동아리 활동의 경우 짧은 기간동안 기획자, 게임 아트 디자이너, 프로그래머가 모여 프로젝트를 진행하는데, 자체엔진을 사용하면 컨텐츠가 추가될 때 엔진 기능들도 개선하면서 진행해야 하기 때문에 시간내에 프로젝트를 완성하기 힘들다 생각해서 활동에 참여하는데 어려움이 많았습니다.
또, 상용엔진에 비해 성능이 떨어지고, 게임의 그래픽적인 요소에서도 많이 떨어진다 생각합니다.
때문에 Unreal Engine이나 Unity를 공부해야겠다 생각이 들었고, 저는 PC게임 장르를 개발하고 싶은게 첫 목표라 PC게임 개발 쪽에 많이 쓰이는 Unreal Engine에 대한 공부를 시작하려합니다.
UNSEEN에 참여해 보다 깊이있게 배우면 좋았겠지만 1차 서류에서 떨어져서 너무 아쉽네요.. ㅠㅠ
Unreal Engine은 Udemy의 강의를 들으며 따라하고, 그 날 공부한 내용들을 블로그에 포스팅하면서 정리해볼 생각입니다.
정리의 경우 우선 Unreal의 기초적인 용어나 기본 셋팅과 강의를 보고난 뒤 간략한 정리 등만 포스팅할 계획이고, 계속 공부해서 직접 프로젝트를 진행할 때, 새로 찾은 내용이나, 오류등에 대해 포스팅할 것 같습니다.
https://www.udemy.com/course/unrealcourse/
1. Intro 및 Setup
프로젝트를 처음 생성할 때, 설정을 보면 다음과 같은 창이 나온다.
블루프린트나 C++의 경우 블루프린트 전용으로 프로젝트를 구성할지, 블루프린트와 C++클래스를 함께 사용해 프로젝트를 구성할지를 정할 수 있다.
(검색해본 결과 블루프린트만으로 프로젝트를 진행하면, C++ 코드를 사용하지 못한다고 한다.
때문에 블루프린트로 만든 프로젝트에서 C++ 클래스를 사용하려면, 프로젝트 세팅을 변경해주어야 가능하다고 한다.)
타깃 플랫폼은 해당 프로젝트로 만든 프로그램이 어떤 환경에서 실행될 것인지 정해 프로젝트를 만들 수 있다.
퀄리티 프리셋의 경우 최대로 하고, 컴퓨터 성능이 부족해 개발에 문제가 생긴다면, 프로젝트 내부에서 퀄리티를 낮출 수 있다.
(엔진 퀄리티의 경우 해상도 스케일, 뷰 거리 안티에일리어싱, 포스트 프로세스 등 다양한 값을 직접 조절할 수 있고, 간단하게 지정할 수 있는 프리셋들도 존재한다. 직접 조절할 때는 콘솔명령어를 통해 직접 조절할 수 있는 것 같다.)
Scalability, 엔진 퀄리티 레퍼런스
Scalability, 엔진 퀄리티 옵션, 프로퍼티, 콘솔 변수입니다.
docs.unrealengine.com
시작용 콘텐츠는 기본 콘텐츠를 포함해 프로젝트를 만들지 정해주는 것이기 때문에 직접 프로젝트를 진행할 때 굳이 사용할 필요가 없다면 체크박스를 해제하고 진행하면 된다.
레이 트레이싱의 경우 듣고 있는 강의에서는 GPU 성능에 따라 끄고 키는게 좋다고 한다.
(레이 트레이싱에 대해서는 우선 기본적인 Unreal 공부를 마치고 공부해보려 한다.)
뷰 포트(Viewport)는 현재 실행하고 있는 Level을 3D preview를 제공한다.
뷰 포트의 조작법
우 클릭 상태에서 드래그 - 화면을 회전할 수 있다.
우 클릭 상태에서 마우스 휠 입력 - 뷰포트를 찍어주는 카메라 속도를 조절할 수 있다.
W,A,S,D - 화면을 이동해볼 수 있다.
Q,E - 화면을 위, 아래로 이동할 수 있다.
실행 버튼은 해당 Level을 미리 실행해 볼 수 있고, 일시 정지, 정지가 가능하다.
실행 버튼으로 Level을 실행해 캐릭터를 활성화해 제어해볼 수 있는 등 작업 도중에 해당 Level을 테스트해볼 수 있다.
아웃라이너(OutLiner)는 현재 Level에 존재하는 모든 Actor(오브젝트)를 확인할 수 있다.
콘텐츠 브라우저는 해당 프로젝트 폴더내에 있는 리소스나, 블루프린트 클래스, Level, Marterial 등을 쉽게 확인할 수 있다.
아웃라이너나 콘텐츠 브라우저등 일부 툴 창을 닫았는데, 다시 키는 방법을 모른다면, 아에 디폴트 레이아웃을 불러와 다시 사용하는 것도 방법이다.
엔진 퀄리티 설정
세팅 -> 엔진 퀄리티 세팅에 들어가면, 위에서 설명했던 퀄리티 세팅 프리셋이 나온다. 이중 알맞은 것을 선택해 엔진 퀄리티를 낮춰 보다 쾌적하게 프로젝트 작업을 할 수 있다.
2. Moving & Placing Actor
우선 위에서 Level이나 Actor가 어떤 단어인지 설명을 하지 않았다.
Level은 쉽게 생각하면, 게임의 스테이지와 비슷하다.
Level은 Stage, Scene에 해당되는 게임이나 영상이 진행되는 장면이라고 생각하면 된다.
Actor는 말 그대로 배우로, Level을 구성하고 있는 박스나 플레이어등의 물체를 말하는 것이다.
위에서 설명한 아웃라이너에서 Actor를 선택해 바로 해당 Actor를 수정할 수 있고, 뷰포트(Viewport)에서 직접 마우스로 클릭해 수정할 수 있다.
Actor나 폰, 박스(기본 도형) 등의 생성은 뷰포트 상단에 있는 "프로젝트에 빠르게 추가하기"를 눌러 원하는 Actor를 쉽게 Level에 생성할 수 있다.
언리얼 엔진의 오브젝트 기초 클래스인 UObject에 대한 내용.
Unreal Engine에는 게임 오브젝트 처리용 시스템이 있는데, Unreal에서의 오브젝트의 베이스 클래스는 UObject이다.
해당 UObject로 부터 파생해 다양한 오브젝트 클래스들이 생겨난다.
UObject 클래스에서 제공되는 함수성들은 다음과 같다.
◈ Garbage Collection
Unity나 java 이상급 언어에는 해당 GC가 들어가 있는 경우가 많다. 본래 C++에서 메모리는 사용자가 관리하지만,
UObject에서는 이 기능을 제공한다.
Unreal 코드를 작성할 때, UPROPERTY() 메크로를 사용해 UObject를 상속받을 수 있다.
혹은 스마트 포인터와 같은 개념으로 메모리를 관리할 수 있다.
◈ 레퍼런스 자동 업데이트
AActor 또는 UActorComponent가 소멸되거나 다른 식으로 플레이에서 제거 되면, 리플렉션 시스템에 보이고 있는
그에 대한 모든 레퍼런스는 자동으로 null이 됩니다.
이는 허상 참조를 예방하여 문제의 소지를 줄인다는 장점이 있다. Unreal의 경우 null 검사 안정성이 높은데,
일반적인 null 포인터의 경우와 null이 아닌 포인터가 삭제된 메모리를 가리키는 경우 둘다 감지해낸다.
중요한 점은 이러한 기능은 UPROPERTY로 마킹되어 있거나 언리얼 엔진 컨테이너 클래스에 저장된
UActorComponent, AActor의 레퍼런스에만 적용된다는 점이다.
(raw 포인터에 저장된 오브젝트 레퍼런스는 언리얼 엔진이 알지 못하기 때문에 자동으로 null이 되거나,
Garbage Collection이 방지하지 못한다. 이럴 경우 TWeakObjectPtr 사용을 고려해보라고 한다.)
◈ Reflection
코드를 실행하는 런타임 도중에 클래스 안의 변수나 함수등의 정보를 알고 싶을 경우 사용하는 기능이다.
C++에서는 본래 reflection을 지원하지 않지만, Unreal Engine에서 별도로 제작했기 때문에 코드를 수정하지 않고
엔진 자체적으로 클래스를 수정하거나 하는 작업을 할 수 있다.
◈ Serialization
직렬화, 백엔드 측면에서 데이터를 주고받을 때 주로 이용되는 개념이다.
코드를 실행하여 생성된 인스턴스 안에 특정 값들이 들어갔을 때, 이는 메모리에 올라가 휘발성을 가지고 있다.
따라서 직렬화하여 다른 공간에 저장하는 역할을 할 수 있다.
◈ 디폴트 프로퍼티 변경사항 자동 업데이트
UClass의 클래스 디폴트 오브젝트(CDO)가 변경되면, 엔진은 그 클래스의 모든 인스턴스 로드시
알아서 변경사항을 적용하도록 시도합니다.
즉, CDO가 변경되면, 오브젝트 인스턴스로 생성된 모든 오브젝트들은 해당 CDO를 기준으로 저장된 값이
업데이트 된다는 의미같다.
◈ 자동 프로퍼티 초기화
UObject는 생성자 호출 전 초기화시 자동으로 0으로 채워진다.
클래스, UProperty, 네이티브 멤버 모두에게 전체적으로 일어나는 일이다.
그 이후 멤버는 클래스 생성자의 커스텀 값으로 초기화 가능하다.
◈ 자동 에디터 통합(Automatic Editor Intergration)
코드가 아닌 엔진 자체적으로 블루프린트 같은 기능으로 작업할 수 있는 기능이다.
블루프린트와 비주얼 스크립팅의 통합이 가능하다는 뜻으로 C++ 코딩시 변수와 함수의 노출 및 접근 여부를 제어
할 수 있는 옵션이 많이 있다는 뜻이다.
◈ 실행시간에 유형 정보 사용가능
정리하자면 UObject는 언리얼 엔진 리플렉션 시스템의 일부로, 자신이 어떤 UClass인지 알고 있기 때문에,
형변환을 실시간으로 할 수 있다는 것이다.
C++의 상속구조와 가상 함수, 함수 오버라이딩의 내용과 유사하다.
◈ 네트워크 리플리케이션 (Network Replication)
100명 안으로 비교적 적은 인원의 클라이언트 - 서버 구조를 만들 때 유용하다.
특히 동기화의 측면에서 UObject를 상속 받음으로써 자동으로 네트워크 동기화 기능을 가능케 한다.
Actor의 경우 UObject를 상속받은 AActor 클래스로 만들어지고, 폰(Pawn)은 AActor를 상속받아 만들어진다. 또, 캐릭터(Charactor)는 폰을 상속받아 만들어진다.
Actor를 상속받으면, Component를 사용할 수 있게되고, Pawn을 상속받으면 Controller를 이용해 조작할 수 있게된다.
Charactor를 상속 받으면, Charactor Movement라는 Component가 제공된다. (즉, 캡슐을 기반한 이동기능을 이용할 수 있게된다.)
이 처럼 아웃라이너에 존재하는 오브젝트들은 모두 기본적으로 UObject 클래스를 상속받아 만들어진 오브젝트들이다. (대부분이 AActor를 상속받는 것들일 텐데, 모두가 그런지는 정확히 모르겠다. 조금 더 자새히 공부해야겠다.)
엑터를 선택하게되면, 기즈모로 3방향의 화살표가 나타난다.
화살표를 눌러 해당 방향으로 물체를 이동할 수 있고, 축2개가 이루는 직각 표시를 클릭해 이동하면 2축을 기준으로 면이동이 가능하다.
위의 초록색 부분의 아이콘을 눌러 각각 액터 선택, 이동, 회전, 스케일 변경으로 모드를 변경해 쉽게 변경할 수 있고,
Actor를 선택한 뒤 W,E,R을 입력해 단축키로 모드 변경이 가능하다.
또 해당 수치들은 디테일 탭에서 수치를 입력해 변경해 볼 수 있다.
ctrl + c, ctrl + v를 이용해 선택한 액터를 쉽게 복사해 생성할 수 있다.
뿐만아니라 액터를 선택한 뒤 alt키를 눌러 이동하면 복사 생성한 물체를 이동할 수 있다.
또한 아웃라이너에서 액터를 더블 클릭하면 뷰포트에서 해당 액터로 줌되며 이동한다.
(때문에 뷰포트에서 해당 액터의 위치를 찾지 못하면, 아웃라이너에서 더블클릭해 쉽게 액터의 위치를 찾을 수 있다.)
3. C++ versus Blueprint
Blueprint란 언리얼 엔진에서 내부 구현된 시각 프로그래밍 언어이다.
블루프린트의 장점
a. 변경점이 바로 적용되어 테스트해볼 수 있다.
b. 초보 친화적이다.
c. 내장된 도구가 있기 때문에 쉽게 원하는 기능을 찾을 수 있다.
d. 언리얼 맞춤 제작 언어이기 때문에 언리얼에 최적화되어 있다.
e. 프로그래밍을 잘 모르는 디자이너나 아티스트에게 친화적이다.
즉, 다른 분야에 종사하는 대형팀에 유리하다.
C++ 클래스의 강점
a. 블루프린트에 비해서 간결하다.
수학 연산의 경우 코드로 보는게 더 간결하는 등의 이유이다.
b. 산업 표준 언어이기 때문에 이미 많은 사람이 해당 언어를 알고 있고, 그 만큼 다양한 도구가 존재하고 지원하는 폭이 넓다.
다양한 메크로, 함수 등이 C++로 지원하고 있다. 하지만 블루프린트의 경우 지원해주지 않는 경우가 있다.
또한 C++을 통해서 API를 만드는게 더 쉽다.
c. 속도가 블루프린트에 비해 빠르다.
왜 블루프린트가 느린가에 대해서
1. 블루프린트는 더 많은 명령을 거치게 된다.
해당 이유가 속도와 관련된 주된 이유이다.
블루프린트 함수들은 C++과 달리 객체로 유지된다. 어떤 C++ 함수들을 호출할지에 대한 정보를 가지고 있어야하기 때문에 더 많은 명령을 거치고 cpu, 램 등을 많이 사용하게 된다.
이러한 이유로 인해서 컴파일을 한다 해도 C++의 컴파일러처럼 인라인화를 해주는 이점을 가져오기 못하기 때문에 더 느려지는 결과가 발생하게 되는 것이다.
추가적으로 포럼에서 엔진 기여자의 말을 보면 블루프린트는 항상 메모리를 통해 접근해야 하고 C++로 만들어진 경우 CPU 캐시 힛이 될 여지가 있는 것처럼 이야기한다고 한다. (이는 참고한 블로그에서도 더 찾아봐야할 것 같다고 하니 나도 한번 더 찾아봐야 할 것 같다.)
자료들을 살펴본 결과 블루프린트로 만든 기능이 차이가 심하게 나지 않고 심지어는 차이가 없는 경우도 있다고 한다. 어떤 기능을 만들어 사용하는지에 따라 성능차이가 다르게 나타나는 것 같다.
때문에 무조건적인 블루프린트 지양은 좋지 않다고 한다.
[Unreal] 언리얼 블루프린트 vs C++, 왜 프로그래머는 C++을 써야 하는가?
개요 언리얼을 처음 맛보면 대부분 블루프린트로 시작하게 됩니다. 저 또한 첫 접근은 블루프린트였습니다. 그런데 조금 더 심화된 과정에서는 C++을 위주로 코딩을 하게 됩니다. 이유를 들어보
husk321.tistory.com
d. 언리얼의 모든 영역과 기능에 접근이 가능하다. (블루프린트는 이러한 점들이 제한적으로 접근 가능하다.)
Unreal의 C++코드는 사용자가 볼 수 있지만, 블루프린트 바이너리는 코드를 보여주지 않는다. (지원X)
e. 큰 프로젝트에 적합하다. (대형 게임을 만들 때 블루프린트로 만드는 것보다 훨씬 쉽고, 블루프린트로 프로젝트를 진행하는 경우에는 여러 이유로 블루프린트가 걸림돌이 되곤한다.)
f. 접근 지정자, UPROPERTY, UFUNCTION 등을 통한 접근 제어가 세밀하게 가능하다.
g. 버전 변겨으 직렬화 등을 위한 다양한 데이터 제어 기능이 있다.
h. 버전 관리에서 C++코드는 보기 쉽게 텍스트로 되어있다.
C++과 블루프린트는 기능 대부분을 함께 작동시킬 수 있다.
UnrealEngine 라이브러리는 C++로 작성되지만 그렇다고 블루프린트에서 접근이 아에 불가능한건 아니다.
또 블루프린트로 만들 수 있는 모든 것들은 C++로 만들 수 있다.
따라서 블루프린트와 C++을 함께 사용해 시스템을 만들어 양쪽 세계를 최대한 활용할 수 있다.
이 다음 강의는 블루프린트를 이용한 물리충돌 구현 등인것 같다. 해당 강의를 보며 정리하면서 공부하고, 추후에 다시 한번 더 정리해 포스팅을 할 계획입니다.
해당 강의가 가볍게 쉽게 알려주지만 하나하나 살펴보면 더 찾아보며 공부할 점들이 많아서 궁금증이 생기면 검색해서 공부해보면서 공부를 진행해야할 것 같습니당.