안녕하세요 이영훈입니다
TPS 게임 제작 과정은
프로토타입, 알파, 베타의 순서로 진행이 되는데요
C 기반의 TPS 게임 제작에서는
언리얼 엔진의 주요 시스템인
스켈레탈 메시 애니메이션 시스템과
내비게이션 시스템 등에 대해 알아보며
AI를 제어하기 위해 유한 상태 기계를 활용한
설계 기법에 대한 이해가 필요합니다
그래서 이번 단원에서는
C 기반의 프로젝트 생성과 TPS 플레이어를 생성하고
3인칭 카메라와 외관을 적용하는 방법에 대해 학습하겠습니다
또한 캐릭터 클래스에 대해 이해하고
회전과 캐릭터 무브먼트 컴포넌트를 이용한
이동에 대해 학습하겠습니다
먼저 TPS 프로젝트를 생성하고
플레이어 외관을 적용해 보겠습니다
C 기반의 프로젝트와 TPS 플레이어 생성
C 기반의 TPS 예제를 해 볼 건데요
먼저 TPS가 뭔지 얘기를 해 볼게요
FPS라는 게 있고 TPS라는 게 있습니다
FPS는 First-Person Shooter의 약자고요
그리고 TPS는 Third-Person Shooter입니다
그래서 이건 1인칭이고요
이거는 3인칭이다 이렇게 보시면 되고요
보통은 이렇게 화면이 있으면 여기에
캐릭터의 손만 보이면 1인칭 손만 이렇게 나온다 그러면 이거는 FPS라고 할 수 있고요
그다음에 화면에 캐릭터 전신이 살짝 보인다
뒤통수가 보인다 이러면 3인칭이라고 할 수 있습니다
이거는 Third Person
그래서 이번 예제는
이렇게 Third-Person Shooter 예제를 해 보도록 할게요
그러면 먼저 프로젝트를 만들어야겠죠
언리얼 프로젝트 브라우저를 여시고
그다음에 게임의 Blank 템플릿을 선택합니다
그리고 여기 C 로 진행하도록 할게요
이름은 Cpp니까 Cpp_를 접두어로 써주고요
TPS라고 하겠습니다
프로젝트가 만들어지면 제일 먼저
우리가 할 일들을 하면 되겠죠
일단 저는 레이아웃을 제가 원하는 형태로 바꾸고요
그리고 먼저 레벨을 하나 만들어 주겠습니다
여기서 File에서 New Level
이번에는 TPS니까 땅이 있어야겠죠 바닥이
그래서 이번엔 Basic으로 시작해 보도록 할게요 Create 합니다
그리고 여기에 이제 게임 모드와 주인공을 만들어야겠죠
이것은 C 로 제작해 보도록 할게요
먼저 게임 모드를 만들겠습니다
여기서 이렇게 하고
이건 TPS니까 앞에 TPS라고 접두어를 적어주겠습니다
Public을 클릭하고요 Create 합니다
그러면 이렇게 잘 만들어진 걸 볼 수 있고요
여기도 한번 로드를 해주시면
파일이 잘 생성되어 있는 걸 확인할 수 있죠
그리고 주인공도 만들어 볼게요
Tools에서 Add C Class 여기에서
이번에는 캐릭터를 만들겠습니다
캐릭터는 Actor, Pawn, Character 이렇게 되어있죠
Actor를 Pawn이 상속받고
Pawn을 Character가 상속받는 구조입니다
여기에서 Character를 선택하고 Next 한 다음에
이거는 주인공이니까요 Player
이건 너무 기니까 Player라고 하겠습니다
Player라는 이름을 쓸 수가 없네요 그러면
TPSPlayer 이렇게 작성해 줄게요 Create 합니다
그러면 주인공도 만들어졌고요
이것을 상속받은 블루프린트를 하나 만들도록 할게요
이렇게 해서 블루프린트 클래스 만들어 주시고
그럼 폴더가 있어야겠네요 여기다가 폴더를 만들 건데
지금 여기서는 생성이 안되네요
그러면 잠깐만요 폴더를 만들고 진행하시죠
Content에 New Folder
블루프린트라는 폴더를 하나 만들게요
그리고 여기 현재 레벨도 저장을 해야 되니까
Maps 폴더도 만들어 주겠습니다
전부 한번 저장을 해주고요
다시 돌아와서 주인공을 만들고요 블루프린트로 BP_
그리고 게임 모드도 만들어 주겠습니다
이거는 우리가 저번에 다 했던 절차니까
그대로 쭉 이어서 해 볼게요
게임 모드도 블루프린트로 만드시고
그다음에 현재 레벨도 저장을 해주도록 할게요
Ctrl S 눌러서 맵에다가 게임 맵이라고 하겠습니다
전부 다 만들었으니까 저장 한번 해주고요
그리고 이것들을 Project Settings에서 지정해 줘야겠죠
Maps & Modes에서 여기 Default Maps에
전부 다 게임 맵을 이렇게 넣어주도록 할게요
그리고 저는 이 Default Modes는 건드리지 않고요
레벨의 월드 세팅 쪽에서 배정을 해주도록 하겠습니다
이렇게 잡아서 넣어도 돼요
그리고 여기에 기본 Pawn은 이것으로 교체해 주고요
그럼 여기를 수정하면 이것도 저장을 해줘야겠죠
이것도 컴파일하고 저장하기를 합니다
이거 계속 눌러야 되니까
Save on Compile - Always로 변경
이렇게 하고 전체 저장도 한번 해줍니다
이렇게 하고 실행하면 이제 주인공이 이곳에 태어나게 되겠죠
현재 레벨에 기본적으로 플레이어 스타트도 있습니다
여기에서 태어날 것 같아요
그러면 이 주인공을 더블클릭해서 외형을 설정을 해줘야겠죠
그런데 우리가 처음에 Blank로 만들었기 때문에
아무것도 없습니다 그렇죠? 그래서 여기에서
외형을 사용하기 위해 기존 템플릿의 데이터를 가져옴
여기서 Add 버튼을 누른 다음에 상단에 보시면
Add Feature라는 게 있습니다 이거를 클릭해 보시면
기존에 있는 내용을 가지고 올 수가 있는데요
여기서 우리는 Third Person 3인칭으로 사용할 것이기 때문에
이것을 선택하고 Add to Project 하겠습니다
블루프린트인 것을 가져올게요 우리가 이걸 가지고
C 로 하면 이거 자체를 다 가져오기 때문에
이걸로 가져오겠습니다
그럼 여기에 복사가 된 것을 볼 수 있고요
이거는 닫아 주시면 되겠습니다
그러면 여기 있는 BP_Third Person
이게 여기 자동으로 들어가 있죠
이거를 사용할 건 아니고요
우리가 만든 걸 쓸 거니까요
여기서 블루프린트 폴더로 돌아와서
여기 BP_TPS Player를 더블클릭해서
여기다가 지정을 해주겠습니다
여기 보면 Character를 상속받은 경우에는
기본적으로 이렇게 4가지 컴포넌트가 붙어있는데요
기본적으로 루트에 캡슐 컴포넌트가 붙어있고요
그래서 이 캡슐 모양이 충돌체 역할을 하게 됩니다
그리고 Arrow 이게 앞쪽이라는 의미를 가지는
Arrow 컴포넌트가 있고 그다음에
Skeletal Mesh Component가 있어요
그래서 여기에는 뼈대를 가지고 있는
그러한 Mesh를 넣어주면 됩니다 그리고 마지막에
캐릭터 무브먼트라는 컴포넌트가 있는데요 바로 이것이
캐릭터 무브먼트 : 실제 캐릭터를 조작할 때 움직임을 제어하기 위해 사용되는 컴포넌트
그래서 보면 여기에 Walking이라든지 Falling, Jumping
이런 것들이 이미 구현이 되어 있습니다
그래서 우리는 이것을 사용해서
움직이거나 점프를 하거나 이런 행위를 해 보도록 하겠습니다
일단 외관을 먼저 설정해 줄게요
Mesh를 선택하신 다음에
여기 디테일에 보면 Mesh라는 카테고리가 있죠
여기에서 Skeletal Mesh Asset에 None이라고 되어있는데
이걸 펼쳐 보시면 여기에 사람 모양의 Mesh가 보입니다
여기에서 저희가 사용할 것은
Quinn을 사용해 볼까요?
SKM_Quinn을 사용해 보도록 하겠습니다
그러면 이렇게 넣으면 이 녀석의 중점이라고 하죠
이 녀석의 원점, 중점 그것은 중앙 하단이 되겠습니다
그래서 이렇게 나오는데
우리는 이것을 좀 내리고 이렇게 회전도 시켜줘야겠죠
얘가 지금 오른쪽을 보고 있으니까요 그래서
Mesh에 보면 상단에 Transform이 있는데요 여기서
Z를 -90으로 내려줍니다 왜 90이냐면
기본적으로 이런 모델링의 크기는
키가 180이 기준으로 되어있어요
그래서 중앙에서 그다음 90cm를 아래로 내려주시면
딱 여기에 맞게 됩니다
그리고 Z축을 이렇게 회전시켜 줄 거예요
이렇게 시계 방향이 증가하는 쪽이니까
반대 방향으로 할 거니까
반대 방향으로 90도 회전시켜 주겠습니다
여기다가 -90도 이렇게 회전하면 되겠습니다
이러면 이렇게 앞쪽을 바라보게 설정을 할 수가 있고요
그러면 이렇게 처리를 하면 되는데 실제로
주인공 캐릭터의 뒤에 카메라가 들어감
우리가 2D 슈팅에서는 카메라를 이렇게
레벨에 배치해서 사용을 했는데요
TPS의 경우에는 주인공을 따라다녀야 되는 카메라잖아요
그래서 여기다가 카메라를 배치합니다
여기다 Add 버튼 누르고 카메라라고 해볼게요
이렇게 카메라가 있죠
카메라를 이렇게 넣어서 배치를 합니다
일단은 블루프린트로 설정한 다음에 C 에서 작업
그런데 카메라 같은 경우에는
이거를 눈 위치에 이렇게 놓으면 FPS가 되는 거예요
이렇게 하고 한번 실행을 해볼게요
그러면 이렇게 되는 거죠
F8을 누르면 카메라 시선을 바꿔 주변에서 볼 수 있음
플레이어가 이렇게 서 있는 것을 볼 수 있고
카메라 위치는 눈 위치에 있기 때문에
다시 F8을 누르면 다시 들어갈 수 있죠
이렇게 지정이 되는 겁니다
3인칭 카메라와 외관 적용 방법
다음은 3인칭 카메라를 설정해 보겠습니다
그런데 그냥 카메라만 넣어도 됩니다
근데 카메라만 넣었을 때 좀 문제가 있어요 어떤 게 있냐면
지금 이거는 FPS니까 뒤로 이렇게 뺄 거예요
이렇게 보면 뒤통수가 보이겠죠
그러면 이렇게 보면 정면이 안 보이잖아요
그래서 보통 TPS 게임들이 이렇게 하는 게임도 있고
약간 측면에서 바라보게 하는 경우도 있습니다
그래서 그런 것들을 처리하기 위해서는
그냥 카메라 하나 가지고 하기에는 조금 어려움이 있어요
그래서 이 카메라의 부모 위치에다가
스프링 암이라는 거를 하나 넣을 거예요
그래서 그 녀석을 이용해서 위치를 보정한다든지
그리고 스프링 암의 재미있는 기능 중에 이런 것도 있습니다
예를 들어서 그림으로 볼까요?
이런 경우가 있어요 플레이어가 이렇게 있고요
카메라가 이렇게 보고 있습니다
그러면 여기 사이에 벽이 이렇게 있을 수 있잖아요
그럼 이렇게 쳐다보면 벽이 보이겠죠
그러면 문제가 되잖아요 이런 경우에
우리가 스프링 암이라는 걸 넣으면
스프링 암이라는 게 있는데 이 컴포넌트를 감싸주면
스프링 암을 활용하여 카메라의 위치가 벽 너머로 이동함 자동으로 이쪽으로 이동합니다 카메라가
이렇게 쳐다보게 바뀌어요
그래서 그런 기능도 쓰려고
컴포넌트를 한번 여기다가 붙여보도록 하겠습니다
캡슐 컴포넌트를 선택하고 Add 버튼을 누른 다음에
여기 Spring이라고 쓰겠습니다
그러면 이렇게 스프링 암이라는 것이 나오는데 클릭하시고요
그다음에 카메라를 여기다 이렇게 넣겠습니다
이러한 하이라키 구조를 가져갈 거고요
이렇게 하면 카메라가 뒤로 확 밀려져 있죠
일단 카메라는 다시 원점으로 놓겠습니다
그리고 보면 스프링 암이 이렇게 되어 있네요
그래서 위로 좀 올릴게요 이렇게
제가 지금 카메라를 조작하는 것이 아니라
스프링 암을 움직이고 있습니다
스프링 암을 약간 오른쪽으로
뒤에서 봤을 때 오른쪽 방향으로 살짝 밀어보도록 하겠습니다
40, 70 이 정도 할까요?
이렇게 하고 보면 이런 식으로 보이게 되죠
조금 더 밀어도 될 것 같습니다
그리고 스프링 암을 보면
카메라를 우리가 뒤로 따로 밀지 않았는데도
카메라가 뒤로 가 있죠
이것은 스프링 암의 속성에 보면
여기 카메라에 Target Arm Length라는 게 있습니다
이게 300이라서 그렇고요
이거를 200이나 이렇게 줄여주시면
이렇게 가까워지는 걸 볼 수 있고
이걸 0으로 하면 바로 앞에 붙게 됩니다
그래서 저는 이걸 200이라고 할게요
그리고 실행을 한번 해 보고요 이렇게 되겠죠
그럼 이 부분을 C 로 구현을 해 보도록 할게요
이쪽으로 가서 플레이어의 헤더 파일로 이동하고요
그러면 방금 우리가 추가했던 내용들 있죠
여기 보면 스프링 암과 카메라 이 두 가지를 추가했고
이 메시에다가 메시 애셋을 이렇게 지정을 해줬습니다
이 일을 코드로 작성해 보도록 하겠습니다
먼저 헤더로 와서 카메라와 스프링 암 두 가지를 추가했죠
그리고 스프링 암을 Attach해서 카메라를 붙였어요
그러면 이걸 먼저 만들어 줄게요
카메라와 스프링 암 코드 작성 UPROPERTY(EditAnywhere)로
class라고 하고요 USpringArmComponent*
이거는 스프링 암이라고 하겠습니다
그리고 이거를 그대로 복사해서
카메라 코드 작성 카메라도 만들어야겠죠 UCameraComponent*
이거는 캠이라고 하겠습니다
컴포넌트니까 이렇게 붙일까요?
CamComp, SpringArmComp 이렇게
이거를 이제 생성을 해 줄게요
생성자로 와서 먼저 스프링 암 컴포넌트를 만들어주겠습니다
CreateDefaultSubobject
이렇게 하고요
이거는 USpringArmComponent가 되겠죠
TEXT라고 하고요 이름을 항상 이렇게 지어줍니다
똑같은 이름으로 할게요
그리고 이거를 루트에 붙여야겠죠
이 녀석은 Attach를 하는데
SetupAttachment(RootComponent)에다가 붙이겠습니다
그리고 이거는 헤더를 추가해야겠죠 이렇게 해서
헤더를 이렇게 추가해 주도록 하겠습니다
이거는 GameFramework이 있네요
그리고 카메라도 만들어야겠죠
CamComp = CreateDefaultSubobject
그다음에 여기도 UCameraComponent 그리고 TEXT
CamComp라고 하겠습니다
이것은 스프링 암에다가 Attach를 할 거예요
이렇게 해서 SetupAttachment
이거는 SpringArmComp에 붙이겠습니다
이것도 마찬가지로 헤더를 include 해주셔야겠죠
이것도 Camera/CameraComponent인 것 같습니다
이렇게 작성을 해주시고요 그다음에
세 번째는 Mesh에 입력한 내용을 실제 코드에 반영하는 형태로 만들기
이거를 하는 방법은 여기에 넣은 애셋이 있습니다
이거는 여기 보면 두 가지 버튼이 있는데
이거는 내가 선택한 것을 넣겠다는 뜻이고요
이거는 이 애셋의 폴더로 가겠다는 뜻이에요
이 폴더를 눌러보시면 이렇게 이동하죠 지금 보고 계시는
Skeletal Mesh를 사용하고 있다고 보시면 되고요
여기서 마우스 오른쪽 눌러서 Copy Reference를 합니다
그다음에 이 내용을 메모장에다가 붙여넣기를 해 보면
이렇게 문자열로 보입니다 이렇게 되어있고요
이 문자를 이용해서 로드를 할 수 있어요
이게 실제로 애셋의 경로라고 보시면 됩니다
실제 애셋의 상대 경로
그래서 이것을 이용해서 Mesh에다가
값을 채워보도록 할게요
먼저 ConstructorHelpers라는 클래스가 있습니다 여기 보면
FClassFinder와 FObjectFinder라는 템플릿 구조체가 있어요
그러면 이렇게 되어 있으니까
클래스는 블루프린트 클래스를 로드할 때 사용됨
우리는 애셋을 로드할 거니까 ObjectFinder를 사용하겠습니다
이렇게 작성한 다음에 우리가 여기다가 꺾쇠를 해요
왜냐면 템플릿이기 때문에 이렇게
<>(꺾쇠)를 이용하여 자료형을 적음
어떤 자료형을 할지 아직 정확하게 모르겠죠?
그래서 일단 이렇게 작성을 하고요
그다음에 일단은 TempMesh라고 할까요?
Mesh를 로드할 거니까 이렇게 하고
괄호를 해서 이렇게 만들겠습니다
여기는 이제 문자열이 들어가는데요 TEXT 하고
어떻게 보면 이게 자료형 그다음에 변수 이름
그리고 이거는 생성자 함수를 호출할 때
인자값을 넘기는 부분이 되겠죠
그래서 여기다가 아까 전에 우리가 기재를 해놨었던 것을
여기다가 붙여넣기를 합니다
이게 좀 조심하셔야 되는 게
이거를 그냥 이렇게 붙여넣기를 하면
가끔 이렇게 띄어쓰기가 되는 경우가 있어요
이렇게 하시면 안 됩니다
이런 식으로 해서 넣으시면 안 되고요 딱 붙어있는 상태
원래 카피한 그대로 문자열을 만들어 사용해야 함
보면 여기에 어떤 자료형을 넣어야 되는지가 보이는데요
SkeletalMesh가 적혀있습니다
그래서 이것을 적어줍니다 그리고 이거는 U로 시작합니다
이렇게 하면 되고요
그럼 이것도 사용하려면 당연히 include 해줘야겠죠
Engine/SkeletalMesh 이렇게 되어있네요
TempMesh가 실제 내부에서 로딩을 시도
파일 읽기를 시도하고요 만약에 성공했잖아요
그러면 그거에 대해서 피드백을 받을 수가 있는데
if 하고 만약에 TempMesh가 성공했다면
Succeeded라고 함수가 있는데 이렇게 하면
피드백 확인 후, 처리할 수 있음
사실 이 함수에 들어가보면
이거는 Object라는 객체가 있는데
이 객체가 null이 아니면 성공, null이면 false
이렇게 반환한다고 보시면 됩니다
여기서 이렇게 되어있고요
그러면 실제로 우리가 Mesh에 넣어야 되니까 처리를 해야 되는데
사실 우리가 Mesh를 만들지 않았잖아요
하지만 Character를 상속받았을 때는
기본적으로 이렇게 Mesh가 있습니다
그래서 이것을 가져오면 되는데요
Get Mesh 하시면 돼요 Get Mesh라는 함수를 이용하시면
Character에 존재하고 있는 Mesh를 우리가 받아낼 수가 있습니다
그러면 Mesh를 가져왔으니까
여기에서 SetSkeletalMesh를 해주면 되겠죠
여기에 이제 새로운 Mesh를 넣으라고 되어있는데요
이게 바로 아까 TempMesh에 있던 Object입니다
우리는 지금 이거를 로드를 했는데
이 Object라는 변수에 이렇게
USkeletalMesh라는 객체가 담기게 되는 거죠
이렇게 해서 우리가 로드를 할 수가 있습니다
그리고 마저 해주면 이것이 로드가 되었으니까
이제 Transform 정보도 우리가 넣어줘야겠죠
그래서 이 값을 넣어줄게요
여기 보면 GetMesh에
SetRelativeLocationAndRotation 함수가 있습니다
이걸 가지고 FVector로 하나 넣어주고요
그다음에 FRotator로 이렇게 넣어줍니다
그래서 여기 보면 아까 0, 0, -90 이렇게 되어있었잖아요
이걸 일단 복사를 해 볼게요 Copy
이거는 이렇게 되고요
그다음에 밑에 있는 Rotator도 한번 복사를 해 보겠습니다
이렇게 해서 보면 이렇게 나옵니다
근데 이제 여기에서 우리가 또 학습할 내용이 하나 있는데요
보시면 Rotator는 X, Y, Z가 아닌가? 하고 봤는데
Frotator는 Pitch, Yaw, Roll
이거는 DirectX라든지
아니면 여러분들 드론 같은 거 혹시 배워보셨나요?
거기에 보면 항공 관련된 거 보면
Pitch, Yaw, Roll이라는 용어를 많이 쓰는데요
Pitch, Yaw, Roll은 축과 관련 있는 정보
여기다 일단 넣어보도록 하겠습니다
이건 0, 0, -90이니까 일단 그대로 채우고
그다음에 Rotator에도 넣는데 Rotator는 보면
여기도 보면 Pitch, Yaw, Roll 순서로 넣게 되어있어요 그렇죠? 이렇게
그래서 Pitch, Yaw, Roll을 넣어야 되니까 보시면
분명히 우리가 z에 -90을 넣었는데
Yaw가 가운데 있습니다
주의사항 그래서 0, -90, 0 이렇게 넣어야 돼요
이렇게 해서 이게 주의사항이고요
이거는 Pitch, Yaw, Roll 순서인데
이거를 설명을 잠깐 해 보면
축을 봤을 때 이렇게 되어있잖아요 이게 x, y, z라면
y, z, x 순서로 넣어야 되는 거죠
그래서 요거를 잘 기억하셔야 됩니다
이 Rotator에 넣을 때는 x, y, z 순서가 아니라는 거예요
y, z, x의 순서입니다
Pitch, Yaw, Roll 이라는 걸 기억하세요
Pitch는 끄덕끄덕, Yaw는 도리도리, Roll은 갸우뚱갸우뚱을 나타냄
회전할 때요
그러면 이렇게 넣어주시고요 이거는 다 배치를 했으니까
언리얼 엔진을 잠깐 한번 꺼주고
그다음에 여기서 다시 컴파일 하겠습니다
그리고 아까 생각해 보니까 스프링 암 같은 경우에도
우리가 지정을 좀 더 해줘야 될 것 같은데
아까 전에 어떻게 했었죠? 여기에서 스프링 암에
TargetArmLength를 아까 우리가 200이라고 했죠
이렇게 200이라고 해주고요 그다음에
Spring Length의 위치도 우리가 바꿨어요
이거에 SetRelativeLocation
이거를 0 아까 몇이었죠? 40, 70 이렇게 했나요?
이런 식으로 우리가 작성해 줬었거든요
FVector가 빠졌네요
이렇게 지정을 해줬었거든요
이것도 마저 같이 해줄게요 컴파일 하고요
일단 실행해 보겠습니다
그러면 여기 주인공을 잠깐 볼게요
TPS 플레이어를 열어서 뷰포트를 보면 이렇게 되어있는데요
그러면 우리가 만든 거 말고
아까 전에 블루프린트에서 넣었던 거 그게 남아 있죠
그거는 삭제를 하겠습니다
스프링 암이랑 카메라 이거는 삭제를 해주고요
C 로 제작한 것들만 그대로 남겨 놓음
보시면 우리가 작성했던 내용으로
그대로 잘 반영이 되는 걸 볼 수 있고요
컴파일 한 후에 다시 실행해 보면 이렇게 됩니다
그러면 이제 Input을 처리해 볼게요
Enhanced Input이라는 게 있는데요 여기 보면
Input에 보면 이렇게 되어있죠
기존에 이렇게 입력에 대한 것도 있긴 한데
이거는 우리가 해봤으니까요
이번에는 Enhanced Input으로 처리를 해 보도록 하겠습니다
언리얼에 이미 여기 보면 Third Person 예제를 보면
이렇게 Enhanced Input이라고 있는데요
기본적인 구조는 Input 액션들을 만들고요
그다음에 이것들을 매핑해서 처리하는 구조로 되어있습니다
그래서 우리도 이런 구조를 만들어 볼게요
먼저 폴더를 하나 만들고요 Input이라고 하겠습니다
그리고 액션 두 개를 등록을 해야겠죠
Input에 보면 여기 액션이 있습니다 Input 액션
이거는 Input 액션이니까 IA라는 접두어를 쓰고요
TPSMove라는 걸 하나 만들고요
그대로 복제해서 Ctrl D 해서 하나 더 만들고
이거는 Jump 이렇게 만들어 주도록 하겠습니다 일단 저장하고요
Jump를 보면 얘는 디지털 해서 bool이라고 되어있네요
True, False 처리를 할 수 있음
그리고 Move를 보면 얘는 이렇게 되어있는데
이거를 열어가지고 Axis 2D를 할게요
Move라는 거는 두 개의 축을 사용할 거기 때문에
그래서 2D라고 지정을 해주겠습니다
그리고 마우스 오른쪽 누르고
Input에서 이번에는 Mapping Context를 하나 만들 건데요
이렇게 만들고 이거는 IMC 플레이어 거니까
이름은 TPS 플레이어로 설정
더블 클릭합니다
그럼 매핑을 할 수 있게 이렇게 되어있는데
여기 더하기를 누르면 이렇게 하나씩 추가할 수 있어요
이걸 열어서 우리가 만든 건 이 두 개죠
Jump랑 Move 두 가지를 넣겠습니다
Jump에 해당하는 버튼을 활성화해줘야 되는데
이렇게 누르고 스페이스바를 처리를 할게요
이동은 4개가 있어야겠죠 W, A, S, D 이런 식으로
그래서 앞뒤로 움직이는 거를 저는 x에다 넣을 거예요
왜냐면 축을 보면 앞뒤가 x축이죠 그리고 좌우가 y축이니까
x값에 앞뒤, 좌우를 y값에 넣도록 할게요
그러면 원래 x, y, z 순서이기 때문에
여기 보시면 아까 밸류 타입에 보면
Axis 2D라고 되어있고 Vector로 되어있죠
당연히 Vector는 x, y 순서겠죠
그래서 이렇게 넣어주도록 할 건데요
일단은 키를 할당을 하겠습니다
W, S 해서 이거는 Vertical이라는 개념으로 쓸 거고
이거는 A, D 해서 Horizontal이라는 개념으로 사용하도록 할게요
w는 그냥 누르면 1 이렇게 되겠죠
아무것도 안 누르면 0이고 누르면 1 이렇게 될 겁니다
그럼 S는 누르면 -1이 되어야겠죠
그래서 Modifier 쪽에서 하나 추가를 해줄 건데
여기 보면 Negate라는 게 있어요 이게 음수거든요
그러면 위에 있는 w는 x값에 1이 들어가고요 누르면
안 누르면 0이 되겠죠
그리고 S는 누르면 -1이 x값에 들어가는 개념입니다 기본적으로
이렇게 두 개는 설정을 해줬고요
그러면 A랑 D를 해야 되겠죠
A와 D는 저는 y에다 넣고 싶어요
그래서 여기 Modifier를 하나 추가를 하고요
여기 보면 Swizzle이라는 게 있습니다
Swizzle은 펼쳐보시면 Order죠 순서를 바꿀 수가 있는데
y, x, z 순서로 이렇게 바꿀 수가 있어요
가장 왼쪽에 있는 축에 값을 담는 것이라고 기억하시면 되고요
그러면 y에다 담게 되는 거예요 Swizzle을 해주면
여기 보시면 여러분이 원하시는 값을 바꿔서 넣을 수도 있습니다
일단은 우리는 Swizzle을 통해서 y에다가 넣겠다고 하는 거고요
그러면 A는 음수죠 D는 양수고
일단은 D도 Swizzle을 해줘야 되고요 이렇게
여기 A랑 D 두 개는 y에 넣는 겁니다
근데 D는 양수니까 그대로 넣으면 되는데
A 같은 경우에는 음수예요 -1을 넣어야 됩니다
그래서 하나를 더 추가하고 여기다가 Negate 이렇게
이렇게 넣어주도록 하겠습니다
이렇게 지정을 해주시면 됩니다
전체를 보면 W는 아무것도 안 했고 S는 Negate
A, D는 이런 식으로 처리를 했습니다
그리고 마우스 회전도 처리를 해야 되겠네요
하나를 더 추가하겠습니다
Input을 Move를 복제를 하고요
이거는 Look이라고 하겠습니다
여기에서 매핑을 하나 추가를 하고요
여기는 Look입니다
Look은 마우스 x, y를 입력을 받을 건데요
마우스 x랑 마우스 y요
이렇게 해주고요
x, y니까 y는 Swizzle을 해서 받으면 되겠죠 이렇게
그리고 보면 x는 좌·우인데 y는 상·하잖아요
일반적으로 마우스랑 실제 좌표계의 방향은 반대
그래서 이거를 Negate까지 넣어주겠습니다
이렇게 지정을 해줄게요
TPS 클래스로 이동을 하고요
TPS 플레이어로 이동하고요 아래로 내려옵니다 여기다가
여기다가 IMC와 IA를 입력
UPROPERTY(EditAnywhere) 이렇게 해줘야 담을 수 있을 거예요
class라고 하고요
UInputMappingContext 이렇게 그다음 여기는 이름을 IMC_player
이렇게 기재를 해주겠습니다
그리고 액션도 등록을 해야겠죠
이렇게 해서 이거는 UInputAction이고요
여기는 IMC가 아니라 IA_Move라고 하면 되고요
그대로 복사하고 하나 더 넣을게요 Jump도 있죠
Jump 말고 Move 밑에 Look이라는 것도 추가하겠습니다 이렇게요
그러면 이거에 대응하는 함수를 만들어야겠죠 여기다가
void OnIAMove라고 할게요 이렇게 하고요
Move 그다음에 Look 그리고 Jump
이렇게 3개의 기능을 연결해 줄 건데요 근데 여기에
매개 변수가 있어요 여기다가 이렇게 작성하면 됩니다
const라고 하고요 FInputActionValue라는 게 있어요
이거는 &이라고 하고 value 이렇게 받겠습니다
근데 이걸 사용하려면 헤더를 추가해야 되거든요 이렇게
그러면 이거를 잠깐 검색을 해 볼까요?
여기서 이렇게 검색을 해보시면
이렇게 되어있죠 이거를 추가하면 되는데 보시면
모듈이 Enhancedinput이라고 되어있어요
그래서 이쪽으로 와보시면 제가 미리 적어놨었는데
여기다가 아마 여러분들은 이렇게 적혀있을 겁니다
여기다 콤마 하시고 쌍따옴표 문자열로 하신 다음에
EnhancedInput 아까 전에 여기 있죠
EnhancedInput 이거를 그대로 여기다 작성을 해줍니다
모듈을 등록해야 클래스를 사용할 수 있음
이렇게 등록을 해주시고 이거를 include 하겠습니다
이렇게 해서 상단에다가 하실 때
generated 위쪽에 작성해야 함
이렇게 기재를 해주고요
같은 방식으로 전부다 이렇게 넣어주도록 하겠습니다
구현부를 만들어 주시고요
일단 컴파일을 해볼까요
컴파일 오류가 나네
언리얼이 열려 있어 컴파일 오류 발생
언리얼이 열려있으니까 끄고요
다시 컴파일 해보겠습니다
그러면 잘 성공하는 걸 볼 수 있고요
가끔 이렇게 빨간 줄이 가는데요
이건 일단 무시하고 진행하시면 돼요
그리고 이거를 이제 등록해서 사용하는 거거든요
TPS의 BeginPlay로 이동하여 작성
먼저 플레이어 컨트롤러를 가져옵니다
auto pc라고 할게요 Cast 하고요
현재 지금 이 플레이어를 조작하고 있는
플레이어 컨트롤러를 가져올 수 있는데
그거를 캐스팅해서 플레이어 컨트롤러로
플레이어 컨트롤러죠 이렇게
캐스팅에 성공하면 실제로 조작하는 주인공 플레이어라는 것을 검증
이렇게 해서 GetController라고 합니다
가져온 다음에 이게 성공했다면 pc가 null이 아니라면
물론 nullptr이 아니라면 이렇게 작성해도 되지만
이렇게 써도 돼요
그다음에 ULocalPlayer라는 게 있습니다 여기 보면
Getsubsystem을 가져올 수 있는데요 이렇게
이건 템플릿으로 되어있고요
여기에 UEnhancedInputLocalPlayerSubsystem
이렇게 기재를 해주시면 되고요
여기다가 플레이어 컨트롤러에
Local Player 가져와서 넣어주면 되고요
이거는 당연히 헤더를 추가해야겠죠
이것도 검색을 한 다음에
여기 있는 include를 사용해 보도록 하겠습니다
이렇게 추가를 해주시면 되고요
이걸 일단 받아야겠죠
얘는 서브시스템을 반환하는데요
auto subsystem이라고 해서 받을게요
이렇게 한 다음에 얘도 이제 null 체크를 해야죠
null이 아니라면 subsystem에
잠깐만요 컴파일 한번 하고 가겠습니다
컴파일 일단 성공했죠 subsystem에서 Clear
자동 완성이 안되는데요 일단 적을게요
이렇게 해서 일단 매핑되어 있는 건 다 날려버리고요
다시 매핑을 하겠습니다
여기서 AddMappingContext라는 함수를 호출해서
여기다가 IMC_Player 그리고 0번 이렇게 넣어주면 되겠습니다
이거는 우선순위 같은 개념이에요
그래서 이걸 바로 사용할 거니까
이렇게 넣어서 등록을 해주겠습니다
이것을 구현하고 여기다 등록해서 사용하면 되겠죠
등록을 해 볼게요
등록하기 위한 캐스팅 필요
보면 UEnhancedInputComponent라는 게 있어요
보면 UInputComponent인데 이거를
이걸로 캐스팅해서 사용할 겁니다
이렇게 해서 Cast 해서 사용할 건데
CastChecked라는 것도 있어요
CastChecked 이거는 null 체크까지 다 해주는 개념인데
이렇게 해서 이거를 캐스팅해서 사용하도록 할게요
이렇게 하면 되겠죠
이것도 사용하려면 헤더를 추가를 해야 됩니다
헤더를 자동으로 추가
이렇게 하면 잘 반영이 되는 걸 볼 수 있고요
이것도 이런 식으로 추가를 해 볼게요
이게 자꾸 오류가 뜨는데요
이것도 이렇게 추가를 하겠습니다
이렇게 두 개를 include를 했어요
인클루드로 오류 해결 이렇게 하니까 오류가 없어지네요 빌드를 하고요
그러면 여기다가 연결을 해줘야겠죠
바인드를 해주도록 하겠습니다
EnhancedInput의 경우에는
이게 Action도 있고 Axis도 있고 그렇잖아요
Input은 모두 BindAction으로 설정
BindAction이라고 하고요
그다음에 내가 Move부터 하겠다 그러면
IA_Move 이렇게 넣어주시고
그다음에 ETriggerEvent에 보면 이렇게 있어요
Triggered가 있고요 Started, Ongoing, Completed
이런 것들이 있습니다 여러 가지 있는데
기본적으로 Axis를 처리하려면 Triggered로 하면 돼요
그럼 계속해서 들어오고요
그다음에 버튼 처리를 할 때는
Started와 Completed를 사용하면 됩니다
그래서 이거는 Move니까 Triggered로 하면 되겠죠
this를 넣고요 그다음에 여기에 함수의 주소를 넣습니다
기존의 방식과 크게 다르진 않아요
이렇게 등록해 주시고요
그리고 복제해서 저는 Lookup도
쳐다보는 것도 이렇게 해주도록 할 거고요
이거는 Look이겠죠
Jump도 해보겠습니다 Jump는 버튼 형식이니까
이렇게 해서 Jump라고 하고요
그리고 이건 Triggered가 아니라
눌렀을 때만 발동을 할 거라서 Started로 하겠습니다
여기는 Jump라고 하고요
플레이어 이동 및 회전 처리
다음은 플레이어를 이동시키고
회전 처리를 구현해 보겠습니다
이동부터 해볼까요 이동은
이동을 하기 위해서 일단은 방향을 저장해야겠죠
여기 넘어온 값을 그냥 바로 쓸 수 있는 것이 아니기 때문에
여기서 Direction이라는 변수를 하나 만들고요 Vector로
Direction에다가 담아주도록 하겠습니다
여기 담을 건데요 이렇게 바로 쓸 수 있는 건 아니고요
여기 보면 이 value를 가져와야겠죠
value에서 Get 해서 가져오면 되는데
지금 Move 같은 경우에는 제가 껐지만 보면
Move는 FVector2D로 되어 있습니다
이렇게 해서 가지고 오고요
그러면 이렇게 하면 되겠죠
그러면 여기에 있는 값을 여기다가 똑같이 넣어주면 됩니다
x에다가 x를 넣고요
그리고 x, y를 쓰고 있으니까
y에다가 y값을 이렇게 넣어주면 되겠습니다
Lookup 회전 함수: AddControllerPitchInput, AddControllerYawInput 그리고 Lookup 같은 경우에는 회전은 이런 함수가 있어요
이게 뭐냐면 Input 회전 값에 대해서
여기다 값을 넣어주면요
일단은 회전 정보를 저장하고 있어요
그다음에 그것을 캐릭터 쪽에서 어디다가 반영할 것이냐
그거를 결정을 해주면 되거든요
일단은 여기서는 Pitch랑 Yaw를 할 건데요
왜냐면 Pitch랑 Yaw가
Pitch는 끄덕끄덕이고 Yaw는 도리도리거든요
그래서 이렇게 회전하고 이렇게 회전시키고
이렇게 회전시키고 이렇게 회전시킬 것이기 때문에
그래서 AddControllerPitchInput, AddControllerYawInput
두 가지를 사용하도록 하겠습니다
이렇게 되겠죠 그럼 여기서 또 가져와야겠죠
같은 방식으로 이렇게 가지고 옵니다
마우스에서 x가 좌·우 그리고 y가 상·하이기 때문에
끄덕끄덕은 y가 되겠죠
vec의 y 값을 여기다 넣어주고요
그다음에 여기다가 vec의 x 값을 이렇게 넣어주면
끄덕끄덕 도리도리 이런 것들을 하게 될 수 있습니다
그다음에 Jump는 이렇게 해요
그냥 Jump라고 하시면 됩니다
이렇게 Jump라는 함수를 호출하면 Jump를 뛸 수 있고요
이렇게 구현을 했고요
그러면 이거를 실제로 이동하는 부분은
T에서 구현을 해줘야겠죠
캐릭터 같은 경우에는 캐릭터 무브먼트라는 컴포넌트가 있는데
그걸 이용해서 이동을 할 겁니다
거기 보면 AddMovementInput이라는 기능이 있어요
여기다가 Direction을 넣어주면 됩니다 이렇게 넣어주고
그런데 Direction이라는 걸 여기서 값을 계속 채우고 있잖아요
그러면 여기 계속 남아있겠죠
그럼 내가 누르지 않아도 갈 수가 있는 거죠
그래서 무조건 이거는
Direction을 한번 처리한 후에는 ZeroVector를 넣어 초기화
누를 때만 값이 들어가고 떼면 Zero가 되는 거죠
그럼 안 움직이겠죠 이렇게요
한번 결과를 보도록 할게요
그러면 플레이어 쪽에 입력하는 내용들을 다 넣어줘야 됩니다
입력하는 부분이 여기 있네요
여기다가 IMC 여기는 우리가 만든 거를 넣어주시고요
그다음에 Move는 TPS라고 되어있는 것들
TPSLook, TPSJump 이렇게 넣어주시면 됩니다
컴파일 해주고요 한번 실행을 해 볼게요
그러면 회전이 되고요
상하좌우로 회전이 되고 이렇게 움직여지죠
근데 상하좌우로 회전되는 거는
제가 뭔가 설정을 좀 했어요 보시면
회전하는 거는 기본적으로 이렇게 이렇게 이렇게 3개
셀프가 있고 그다음에 여기 스프링 암이 있죠
그리고 캐릭터 무브먼트가 있습니다
여기 보면 rotation이라고 한번 보세요
검색해 보면 이렇게 체크되어 있죠 여기 보면
Pawn에 Use Controller Rotation Yaw라고 되어 있고
그다음에 원래는 여기 체크가 안 되어 있어요
그래서 여러분들은 실행해 보시면
아마 이렇게만 회전이 될 거고 이동은 될 겁니다
근데 이동도 이상해요 나는 뒤를 보는데 뒤로 가죠
w 누르는데 절대적인
이동이 부자연스러움 저 앞쪽으로만 가고 이렇게 처리가 되는 걸 볼 수 있는데요
이런 것들을 좀 해결을 해줘야겠죠
먼저 회전부터 볼게요 회전은 기본적으로 이렇게
AddControllerPitchInput/YawInput이라는 값에다가
이렇게 회전값을 넣어주면요
실제로 회전하는 정보를 일단은 가지고 있습니다
이거를 반영하는 것은 여기 있는
옵션을 통해 회전 반영
그래서 셀프는 실제로 TPSPlayer 자체를 말하는 거잖아요
TPSPlayer의 Yaw에 대한 회전축에다가
컨트롤러의 값을 사용하겠다 이런 뜻입니다
그러면 Pitch를 체크해 보면 이렇게 되는 거죠
회전하면 이렇게 누워 버리는 거죠
이렇게 F8을 누르면 빠져나올 수 있는데
이런 식으로 되는 거예요
그래서 이건 아니고 저희가 하고 싶은 거는
Pitch는 이거를 회전하는 게 아니라
카메라만 회전하고 싶어요
그래서 여기에는 그냥 그대로 두고요 그다음에
Spring Arm - Use Pawn Control Rotation 체크
이렇게 하고 실행을 해보면 이런 식으로 처리가 되는 거죠
그다음에 마지막으로 Jump도 이렇게 하죠
근데 마지막으로 이거를
바라보는 방향으로 이동을 해야 될 것 같아요
지금 보면 절대적인 방향으로 움직이고 있거든요
이쪽을 보더라도 앞쪽을 가겠다고 했는데 이렇게 가요
이거를 해결해 보도록 할게요
플레이어로 와서요 여기서
Tick으로 갑니다 Tick에서 이거를 처리를 해 줄 건데
이 Direction 방향을요 절대적인 방향이죠
절대적인 방향을 나를 기준으로 회전하고 싶다라는 거죠
그러니까 무슨 말이냐면 앞쪽이에요
그러면 원래 동서남북 이런 식으로
동쪽 이렇게 북쪽 이렇게 되는 건데
나를 기준으로 이동하게 만듦 그거를 나를 기준으로 앞쪽 이렇게
그런 식으로 Direction 값을 바꿔주도록 하겠습니다
어떻게 하냐면 이렇게 할 수 있어요
Direction = FTransform이라고 하고요
그다음에 여기서 GetControlRotation이라는 게 있습니다
컨트롤러 쪽에 입력받은 회전 값을 그대로 가져옴
지금 우리가 여기다 이렇게 집어넣었잖아요
그러면 거기에 저장되어 있는 회전 값을 가지고 옵니다
그다음에 이거를 기준으로 TransformVector라는 게 있어요
블루프린트에서는 이게 TransformDirection 이렇게 되어있는데
이거는 TransformVector라는 이름으로 되어있습니다
여기다가 Direction을 이렇게 넣어주시고 변환하시면 돼요
이러면 지금 저장된 컨트롤에 들어있는 회전 방향으로
기준을, 축을 바꿔서 반환을 해줍니다 이렇게 되고요
그러면 이걸 가지고 컴파일 한 다음에 결과를 볼게요
실행을 해보면 제가 이쪽을 쳐다보고 w를 누르면
이쪽으로 이제 이동을 하게 되죠 이렇게 하고 이렇게
그래서 이런 식으로 제어를 할 수가 있다는 부분이고요
그리고 플레이어 같은 경우에 우리가 이런 식으로 했는데
지금은 얼굴을 볼 수가 없거든요
제가 이렇게 하고 회전을 이렇게 해보면
절대로 얼굴을 보여주지 않아요
뒤통수만 볼 수 있는데
보통 롤플레잉 게임들, RPG 게임이라고 하죠
그런 게임들에서는 얼굴을 볼 수 있죠
그리고 얼굴을 보더라도 w를 딱 누르면
뒤를 돌아서 가게 됩니다
그래서 그런 처리도 할 수가 있어요 어떻게 하냐면
여기에서 셀프, 본체 회전은 하지 않고요 이걸 꺼주시고
그다음에 캐릭터 무브먼트가 있죠 여기에 보면
Rotation을 검색했을 때 이렇게 나와요
여기에 Orient Rotation to Movement라는 게 있습니다
이거를 체크해 주신 다음에 컴파일 하고 실행을 해보면
이제 이렇게 할 수가 있죠 얼굴을 이제 볼 수가 있고요
이렇게 얼굴 보다가 w를 누르잖아요
그러면 내가 이동하는 방향으로 회전해 버립니다
w를 누른 상태에서는 이런 식으로 회전을 하게 돼요
누르지 않았을 땐 이렇게 되고요
이 기능을 이용하시면
여러분들이 원하는 컨텐츠를 제작하실 때
어떤 콘셉트를 가져갈 거냐에 따라서 이렇게 만들 수 있겠죠
근데 저희는 TPS이기 때문에 이렇게 하진 않고요
그냥 뒤통수만 보도록 하겠습니다
그래서 원래대로 체크를 해줄게요
그다음에 Jump 부분도 있는데요
보시면 Jump 이렇게 뛰잖아요
만약에 두 번을 뛰고 싶다 할 때 설정을 해줄 수가 있는데
Character에 가서 이거는 잠깐 끄고요
그다음에 여기 셀프를 누르고
여기에서 Jump Max Count라고 검색을 해보시면
이런 게 있습니다 1이라고 되어있죠
이거를 2라고 바꾸시면 두 번 띌 수 있어요
이렇게 한 번, 두 번 이렇게 2단 Jump가 가능하고요
이런 식으로 이 값을 어떻게 하느냐에 따라서
Jump 횟수를 바꿀 수가 있죠
그리고 여기 Character Movement에 보시면
Jump에 대한 설정을 할 수가 있는데요
Jumping, Falling이 있죠
여기에 보면 Air Control이 있어요
더 많은 내용이 있는데
여기 보면 Air Control이 있고
이게 0.05라고 되어있습니다 이게 뭐냐면
Air Control은 점프 중에 받는 힘을 설정
굉장히 작은 값을 받게 되어있어서
그래서 지금 보면 Jump를 한 다음에
반대쪽으로 이렇게 눌러보셔도
크게 저항이 일어나는 것 같지가 않아요
계속해서 Jump를 뛴 방향으로 계속 가게 되는 느낌입니다
공중에서도 방향 전환을 하려면 Air Control 값을 증가시킴
이거를 5 정도로 올려 볼게요
이렇게 하고 컴파일 하신 다음에 실행해서 보면
반대쪽으로 이렇게 누르면 저항값이 커지죠
이런 식으로 공중에서도 컨트롤을 할 수가 있는 내용이 있습니다
그래서 이런 것들을 참고하셔서 진행하시면 되겠습니다
이번 단원에서 학습한 내용을 정리하도록 하겠습니다
C 기반의 프로젝트와 TPS 플레이어 생성 캐릭터 클래스의 이해
FPS : First-Person Shooter (1인칭) TPS : Third-Person Shooter (3인칭)
TPS 캐릭터 외관 적용 기획자, 아트, 프로그래머
3인칭 카메라와 외관 적용 방법
SpringArm의 역할 카메라 시야가 막히는 상황을 자동으로 처리함
카메라와 플레이어 사이에 벽이 있을 경우 스프링 암을 활용하여 카메라의 위치가 벽 너머로 이동함
카메라가 저절로 뒤로 밀릴 경우 Target Arm Length를 줄임
플레이어 이동 및 회전 처리
CharacterMovementComponent의 역할 실제 캐릭터를 조작할 때 움직임을 제어하기 위해 사용되는 컴포넌트
이동 처리 방법: Lookup 회전 함수 AddcontrollerPitchInput, AddcontrollerYawInput