8. 용어 정리 - 1
UObject: 언리얼 엔진 내에서 고안된 클래스로 다양한 기능을 제공한다.
(가비지 컬렉션, 레퍼런스 업데이트, 리플렉션 등 C#, JAVA 같은 타 객체 지향 언어의 기능을 엔진에서 제공하고있다.)
AActor: 게임 플레이에 사용되는 클래스. 게임 월드에 존재하는 대부분 오브젝트는 AActor를 상속.
UObject를 상속받지만 가비지 컬렉션에서 관리되지 않음. Destroy 함수를 통해
APawn: AActor를 상속받고 Controller에 의해 조작이 가능한 플레이어, AI 캐릭터를 개발할 때 사용되
는 클래스.
ACharacter: APawn을 상속받고 Mesh와 CapsuleCollider 충돌체, CharacterMovement 클래스를 기본
으로 가지고 있으며 이동, 점프 등을 기본적으로 구현되어있어 플레이어를 구현하기 위한 구성이 되어
있는 클래스. (APawn과 차이는 이족 보행 캐릭터를 위한 Pawn이 ACharacter이다.)
9. 용어 정리 - 2
UActorComponent: AActor에 다양한 기능을 가지는 부품과 같은 역할을 한다. 디
자인 패턴 중 컴포넌트 패턴이 적용된 클래스로 별도의 동작 방식이 내장되어있고
AActor에 붙이거나 다른 부모 컴포넌트에 붙일 수 있으며 다수의 자식 컴포넌트를
붙일 수 있다.
USceneComponent: UActorComponent를 확장한 클래스. Transform을 가지고 있
다. 카메라, 오디오 컴포넌트 등 보이지는 않지만 위치값이 필요한 컴포넌트를 개발
할때 상속받아서 사용한다.
10. C++ 클래스 구조 보기
CDO를 정리하기 전 ACharacter을 상속받은 ABaseEnemy의 구조를 먼저 본다.
11. C++ 클래스 구조 보기
C++ 클래스를 생성하고 include 된 파일중 보면 클래스명.generated.h 라는 파일이 있고
언리얼 클래스에는 UCLASS() 매크로를 작성하고 GENERATED_BODY() 매크로는 세트로 와
야한다.
12. C++ 클래스 구조 보기
참고자료: 언리얼 엔진 프로퍼티 시스템(리플렉션)
https://www.unrealengine.com/ko/blog/unreal-property-system-reflection?lang=ko
언리얼 엔진에서 리플렉션이라는 런타임에 클래스의 정보를 알 수 있는 기능이 동작한다. C++
에는 없는 기능으로 언리얼 엔진에서 제공.
클래스명.generated.h에 리플렉션 데이터를 생성해서 넣는다.
13. C++ 클래스 구조 보기
참고자료: 언리얼 오브젝트 처리
http://api.unrealengine.com/KOR/Programming/UnrealArchitecture/Objects/Optimizations/index.html
UCLASS가 선언된 UObject를 상속 받는 언리얼 오브젝트 클래스는 CDO를 유지하는 것 외에
도 가비지 컬렉션, 리플렉션 등 엔진을 위한 다양한 기능을 제공한다.
또 매크로에 인수를 넣는 것으로 추상 클래스 등의 설정이 가능하다.
14. C++ 클래스 구조 보기
참고자료: 언리얼 오브젝트
http://api.unrealengine.com/KOR/Programming/UnrealArchitecture/Objects/
GENERATED_BODY() 아래에 작성되는 변수 및 함수는 접근자가 public이 된다.
15. C++ 클래스 구조 보기
참고자료: 모듈 API 지정자
http://api.unrealengine.com/KOR/Programming/Modules/API/
클래스 사이의 프로젝트명_API 매크로를 통해 언리얼 엔진 클래스는 DLL로 관리되는 것을 알
수 있습니다. 매크로는 상황에 따라 declspec(dllimport), declspec(dllexport) 또는 공란으로 사
용된다.
16. C++ 클래스 구조 보기
그 다음은 기본 생성자와 게임을 실행하면 최초에 한 번 호출하는 BeginPlay와 매 프레임 호출
하는 Tick가 오버라이딩 되어있습니다.
18. C++ 클래스 정리하기
새로 생성한 Enemy와 EnemyController 클래스를 정리하고 싶은데 C++ 클래스에 폴더가 생성이
안됩니다. 드래그 앤 드롭도 안된다.
언리얼 엔진의 클래스는 컴파일 후 CDO라는 것을 생성한다. 런타임에서는 조작불가능.
19. C++ 클래스 정리하기
클래스를 보면서 헤더에서 CDO를 생성하는 것은 보았다. 그럼 정리를 하기 위해서는 직접
Project 폴더의 Source 폴더에서 코드를 정리하는 것 입니다. 언리얼 엔진 스타일로 폴더를 정리
하고 비주얼 스튜디오에도 필터를 만들어서 정리하였다.
20. C++ 클래스 정리하기
그 후 빌드를 해서 엔진을 켜보면 아래와 같이 정리된 것을 볼 수 있습니다.
또 다른 방법으로는 헤더 파일을 옮긴 다음 엔진내에서 컴파일을 진행하면 됩니다.
21. IWYU
(Include-What-You-Use) UE4 4.16↑변경사항
4.16 이전버전에서는 CPP파일에 언리얼 엔진의 대부분 모듈이 포함된 Engine.h, UnrealEd.h 헤더
파일을 포함하였으나 엔진이 커지면서 이 부분이 병목이 되었다고 합니다.
4.16버전부터는 CPP파일에 필요한 헤더파일을 추가해야합니다.
참고자료: IWYU 레퍼런스 가이드
http://api.unrealengine.com/KOR/Programming/UnrealBuildSystem/IWYUReferenceGuide/
23. 핫 리로드
언리얼 클래스가 DLL로 관리되는 것을 알게되었다. 핫리로드는 소스코드를 수정 후 런타임에서
동작하고있는 엔진에 바로 로드하는 기능이다. 이 기능을 사용하는 것으로 코드에서 수정된 로직
을 바로 테스트해볼 수 있다.
엔진과 비주얼 스튜디오가 모두 켜져있는 상태에서 비주얼 스튜디오에서 빌드 완료하면 아래와
같이 핫 리로드 완료! 라는 창이 뜬다.
비주얼 스튜디오 대신 엔진에서 컴파일 버튼을 눌려서 빌드를 해도 된다.
24. 때때로 핫리로드 보다는
Visual Studio에서 빌드
단 핫리로드를 했을 때 생성자에서 수정한 내용은 적용되지 않습니다.아래와 같은 이유입니다.
그래서 엔진을 끄고 코딩을 한 다음 빌드를 해서 엔진을 켜는 것을 때때로 추천합니다.
25. 적 캐릭터 구현 - HP
적 캐릭터의 HP를 float 형으로 추가하는데 이때 언리얼 변수(UPROPERTY)를 사용하여 에디
터에서 값을 표시하거나 수정할 수 있도록 할 수 있다.
26. 언리얼 변수(UPROPERTY)
UPROPERTY에 옵션에 따라 블루프린트 클래스에서 변수를 조작할 수 있다.
Visible은 보여주기만하고 Edit은 수정할 수 있다.
BaseEnemyChar로 여러 종류의 블루프린트 클래스를 생성 후 각각 다른 메쉬와 다른 체력을
기획자가 설정하여 여러가지 몬스터를 만들어 낼 수 있다.
참고자료: 프로퍼티
http://api.unrealengine.com/KOR/Programming/UnrealArchitecture/Reference/Properties/
27. C++ 클래스의 블루프린트 클래스
C++ 클래스를 기반으로 블루프린트 클래스를 생성하면 메쉬 등 다양한 것을 쉽게 설정할 수
있다.
28. C++ 클래스의 블루프린트 클래스
이렇게 보면서 적 캐릭터의 메쉬의 위치나
머티리얼 등을 설정할 수 있다.
29. 언리얼에서의 캐릭터 조작
언리얼에서는 Pawn이 있고 Controller를 이용하여 Pawn을 조작한다.
플레이어
PlayerController
PlayerPawn
EnemyPawn AIController
EnemyPawn
AIController
31. Controller
작명규칙을 보면 AActor를 상속하는 클래스의 접두사 A이다.
컴포넌트는 UObject를 상속하는 UActorComponent가 최상위 부모이다.
Controller 클래스가 컴포넌트였다면 UController이었을 것이다.
하지만 풀네임이 AController이고 Actor를 상속받는 것을 알 수 있다.
참고자료: 작명규칙
http://api.unrealengine.com/KOR/Programming/Development/CodingStandard/index.html
32. Controller
Controller이 Actor를 상속받는 이유는 Controller이 영혼 같은거라고 생각하면 된다.
그리고 그 영혼이 원하는 Pawn을 찾아서 Possess하여 그 Pawn을 조작한다.
엔진에 보면 빙의라고 표현한다. 컴포넌트의 경우 특정 액터에 붙이면 종속되어버린다.
그래서 Controller은 Actor를 상속받는다.
Possess
Controller = 영혼
Pawn = 영혼이 없는 몸
33. 적 캐릭터 구현 - AIController
AIController를 상속받는 BaseEnemyController 클래스 생성. 모든 클래스 표시를 체크하지 않
으면 표시되지 않는다.
34. 적 캐릭터 컨트롤러 구현
간단하게 플레이어를 쫓아가는 적 캐릭터를 구현해본다.
플레이어를 쫓기 위해서는 플레이어의 정보를 알아야한다.
쫓아갈 대상의 액터를 저장하는 변수를 추가하였다.
35. 플레이어 찾기
BeginPlay에서 플레이어를 찾아서 MoveTargetActor에 넣
어준다. 우선 UGameplayStatics 클래스가 가지는
GetPlayerPawn 함수를 사용하여 현재 게임 월드에서 0번
째 플레이어를 찾아주는 기능으로 구현하였다.
Kismet: GamePlayStatics 헤더의 폴더인 Kismet이 무엇인지 궁금할 수 있다.
Kismet은 언리얼 3의 비주얼 스크립팅 이름이다. 언리얼 4는 3를 기반으로 만들
면서 Kismet이 블루프린트로 바뀐 것이지만 하위 호환을 위해 이름을 그대로 사
용하고 있다고 한다.
36. 플레이어 쫓기
MoveToActor은 Pawn의 멤버 함수로 대상 액터까지 네비
게이션 메시를 타고 찾아간다.
두번째 인자로는 어느 거리까지 쫓아가느냐를 넘겨준다.
이때 거리 1Unit = 1cm이다. 현재 코드는 100cm까지 타겟
액터를 쫓아가는 코드이다.
유니티는 1Unit = 1m
37. 적 캐릭터 컨트롤러 설정
BaseEnemyChar로 BP_HumanEnemy를
만들었고 방금 작성한 AI Controller Class
를 적용한다.
AIController은 Component도 아니고 Actor인데 어떻게
Actor에 붙일수 있는가?
Pawn은 멤버 변수로 AI Controller Class를 가지고 있기 때
문에 설정만 해주면 된다.
39. TActorIterator<ActorType>
또 다른 방법으로 플레이어 액터를 찾는다면 EngineUtil.h의 TActorIterator<ActorType>를 사용하여 원
하는 액터 타입으로 찾을 수 있다.
참고자료: UE4 C++ 프로그래밍 입문 → 오브젝트/액터 이터레이터 항목
http://api.unrealengine.com/KOR/Programming/Introduction/index.html
40. Assert
check(값), 값이 false일 경우 엔진 크래시를 발생시킨다.
참고자료: 어서트
http://api.unrealengine.com/KOR/Programming/Assertions/