개요



UE4 에서는 어떤 인스턴스의 근본 구조와 로직은 C++ 클래스를 통해 정의하고, 인스턴스당 특성들은 블루프린트 및 그것의 상속을 통해서 정의합니다.


UT 에서의 캐릭터도 마찬가지의 방식으로 정의되어 있으며, 그 구조는 다음과 같습니다.



GhostCharacter 라는 것은 튜토리얼에서 사용하는 특별한 캐릭터입니다. 그런데 이 구조를 보면서 뭔가 미진함을 느끼시는 분들이 있을 겁니다. DefaultCharacter BaseUTCharacter 에는 메시를 바꿀만한 이벤트같은 것이 존재하지 않습니다. 그러면 어떠한 경로를 통해서 다양한 메시가 나올 수 있는 것일까요? 


결론적으로 이야기하자면 UT 에서 모든 캐릭터는 DefaultCharacter 만 사용해서 생성됩니다. 다음 섹션에서는 이러한 일들이 어떻게 가능한지에 대해 구체적으로 설명하도록 하겠습니다.


Character Content



UT 에서 DefaultCharacter 의 Mesh 컴포넌트는 AUTCharacterContent 라는 액터를 참조하여 대체될 수 있습니다. Mesh 컴포넌트는 이전에도 이야기했듯이 3인칭 관점에서의 캐릭터를 표현하기 위한 컴포넌트입니다.


이 Mesh 컴포넌트를 어떻게 채워야 하는지에 대한 정보를 담고 있는 것이 바로 character content 입니다. UT 에서 AUTCharacterContent 를 상속하여 만든 블루프린트들은 "Content/RestrictedAssets/Character" 폴더에 있습니다.



그중에 NecrisFemaleBase 라는 블루프린트를 열어 보도록 하겠습니다.



열어 보시면 매우 실망스러울 것입니다. Mesh 라는 컴포넌트가 달랑 하나 있는데, 내용이 전혀 채워져 있지 않습니다. 그것은 Base 클래스이기 때문에 그렇습니다. 그렇다면 실제로 뭔가가 할당된 것이 있을까요?


네 있습니다. 단지 하나밖에 없어서 문제지요. "Content/RestrictedAssets/Character/Malcom_New" 폴더에 가면 Malcolm_New 라는 블루프린트 애셋이 있습니다( 폴더 이름과 애셋 이름이 다른 것은 오타가 아닙니다. 실제로 그렇게 되어 있습니다 ). 이것은 HumanMaleBase 를 상속하고 있으며, SkeletalMesh'/Game/RestrictedAssets/Character/Human/Male/malcolm_ut4_SKELMESH.malcolm_ut4_SKELMESH' 를 사용합니다.



여기까지 보시고 나서 "그래서 뭐 어쩌라고?" 라는 질문을 던지시는 분이 계실 겁니다. 당연한 질문입니다.


AUTCharacter 에는 ApplyCharacterData() 라는 메서드가 있습니다. 여기에서 AUTCharacterContent 를 인자로 받아 AUTCharacter 가 가지고 있는 Mesh 컴포넌트를 변경하게 됩니다.



코드를 조금만 읽어 봐도 금방 이해하시겠지만, 요약하자면 팀 재질과 메쉬를 설정합니다.


용례 : Bot



실제로 DefaultCharacterAUTCharacterContent 가 어떤 식으로 연결되는지에 대한 예를 들어 보도록 하겠습니다.


UE4 에서 플레이어의 상태를 저장하기 위해서는 PlayerState 라는 것을 사용합니다. Character 나 Pawn 에 정보를 직접 저장할 수도 있지만, 서버와의 연동을 생각하면 PlayerState 를 사용하는 것이 좋습니다. 언리얼 공식 문서의 [ 게임플레이 프로그래밍 ] 에서는 PlayerState 에 대해 다음과 같이 정의합니다.


인간 플레이어 또는 플레이어인 척 하는 봇과 같은 게임 참여자의 상태를 말합니다. 게임의 일부로서 존재하는 플레이어가 아닌 AI 에는 PlayerState 가 없습니다.

PlayerState 에 적합한 예제 데이터라면, 플레이어 이름, 점수, MOBA 게임류에서의 대전상대 레벨, CTF 게임에서 플레이어가 현재 깃발을 운반중인지 여부 등입니다. 모든 플레이어에 대한 PlayerState는 ( PlayerController 와는 달리 ) 모든 머신에 존재하며, 동기화 상태 유지를 위해 자유로이 리플리케이트 가능합니다.


어쨌든 정리하자면 이 PlayerState 는 플레이어의 정보를 유지하는데 사용됩니다. UT 의 경우에는 AUTCharacterContent  AUTPlayerState::SelectedCharacter 라는 속성을 통해 현재 플레이 대상의 CharacterContent 를 공급합니다.


자 원래 주제로 돌아 와서, UT 에서 Bot 은 UUTBotCharacter 라는 데이터 애셋으로 정의됩니다. "Content/RestrictedAssets/Character/Bots" 폴더에 보면 봇 캐릭터를 정의하는 애셋들이 있습니다. 이것은 실제 캐릭터가 아니라 UDataAsset 을 상속하고 있는 데이터입니다. "Content/RestrictedAssets/Character/Bots/ThunderCrash/Taye" 라는 봇의 데이터를 한 번 살펴 보도록 하겠습니다.



봇의 성격이라든가 목소리라든가 하는 여러 가지 특징들을 정의할 수 있군요. 하지만 우리가 집중할 것은 노란 박스로 강조해 둔 Character 속성입니다. 이것은 다음과 같이 정의되어 있죠.



앞에서 언급한 AUTCharacterComponent 를 사용하도록 메타 클래스를 지정하고 있음을 알 수 있습니다. 그런데 지금은 "None" 으로 비어 있죠? 이 경우에는 위에서 언급한 Malcolm_New 라는 기본 CharacterContent 를 사용하게 됩니다. 이것을 바꾸는 방법에 대해서는 "실습" 섹션에서 논의하도록 하겠습니다.


자 이제 이것이 전체적으로 어떤 관계를 가지는지 클래스 다이어그램을 통해 살펴 보도록 하겠습니다.



우리가 Character 속성에 CharacterContent 애셋을 지정하면, 그것은 AUTPlayerState.SelectedCharacter 에 설정되며, 그것은 다시 ( DefaultCharacter 의 부모인 ) AUTCharacter ApplyCharacterData() 의 인자로 넘겨집니다. 이를 통해서 DefaultCharacter 의 ( 3인칭 메쉬의 ) 외형이 결정되는 것입니다.


여기에서는 봇의 경우만 예로 들었지만, 다른 플레이어 캐릭터의 경우에도 PlayerState 를 가지기 때문에 다를 것이 없습니다.


실습 : Taye



이제 실제로 우리가 원하는 CharacterContent 의 봇에 지정해 보도록 하겠습니다. Taye 는 왠지 여자 이름인 것 같으므로 여자 캐릭터를 지정해 보겠습니다. 일단 "Content/RestrictedAssets/Character/Necris_Female" 폴더로 이동합니다.


1. 먼저 CharacterContent 부터 생성해야겠죠. 다음과 같이 블루프린트 부모로 NecrisFemaleBase 를 지정한 후에, 블루프린트가 생성되면 이름을 "NecrisFemale" 로 변경합니다.



그리고 나서 Mesh 의 "Skeletal Mesh" 항목에 "necris_female_ut4_SKELMESH" 를 할당해 줍니다. 이것으로서 CharacterContent 애셋 생성은 끝입니다. 굳이 애니메이션 돌아 가는 것을 확인하고 싶으시다면 "Anim Class" 항목에 애니메이션을 할당해 봐도 좋겠죠.



다음으로는 봇에다가 이 CharacterData 를 할당할 차례입니다. Taye 봇 데이터 애셋을 열어 "Character" 항목에 "NecrisFemale" 을 할당합니다.



"ExmapleMap" 의 시작부에는 다음 스샷과 같이 봇을 생성하는 곳이 있습니다. 게임에 들어 가서 그 위치에서 "Enter" 키를 누르면 봇이 생성되었다가, 다시 "Enter" 키를 누르면 봇이 죽습니다. 이렇게 몇 번 하다가 보면 Taye 가 생성됩니다. 기본으로는 Malcolm_New 가 생성되므로 구분하기는 어렵지 않을 것입니다. 랜덤으로 생성되기 때문에 인내심이 필요할 것입니다( Blue Team Spawn 에 서서 생성하면 초반에 잘 나오더군요 ). 




아래 그림은 possession 을 해제하고 찍은 스샷입니다. 이상하게도 빙의를 해제하면, 1인칭 메시도 같이 나오더군요. 이 부분은 왜 그런지 나중에 확인해 봐야겠습니다.




원하는 봇만 생성되기를 원한다면 AUTGameMode::AddBot() 메서드를 수정하십시오.

+ Recent posts