본문 바로가기

유니티 게임 개발하기

유니티 게임 개발하기 (3) - 플레이어 캐릭터와 애니메이션 만들기

안녕하세요, 지난시간에 이어 계속 유니티 공부를 하고 있는 개발자, 윈디입니다.

지난번에는 저희의 컨트롤을 따라 오브젝트가 움직이게 만드는 코드를 만들어 보았는데요,

오늘은 한번, 캐릭터와 움직이는 애니메이션을 이용해서 플레이어 캐릭터를 만들어 보려고 합니다.


그럼 시작하도록 하겠습니다!


우선, 지난시간에 만들었던 컨트롤 스크립트는 냅둔 상태로, 캡슐 모양은 삭제하도록 할게요.

이미 다들 아시겠지만, 이제 굳이 그 캡슐이 아니어도 스크립트만 넣으면 어떤 물체든 움직일수 있으니까, 걱정하지 말고 지우시면 됩니다. 그리고.. 필드도 좀 넓혀 둘게요. 10x10x10정도..?



음.. 우선 캐릭터를 임포트 하는 방법부터 살펴보도록 하죠.


벌써 캐릭터용 파일과 애니메이션을 가지고 계신 분들이 있을지 모르겠어요.

저같은 경우에는 수업용으로 받은 플레이어 캐릭터를 편의상 사용할 건데요,

없으신 분들은 Windows-asset store에 들어가시면





이렇게 검색해서 무료인 캐릭터들을 찾을 수 있어요.

유료로 다른 유저분들이 올리신 것도 살 수도 있고요, 여러가지 캐릭터/애니메이션 뿐만 아니라 뒤쪽에 서술할 여러가지 마테리얼( 스킨같은 개념이라고 생각하시면 편합니다.) 들을 다운로드 받아서 임포트 하실 수 있으니까, 참고해 주세요.

유니티 공식홈페이지 아이디가 필요합니다.




하여~ 이렇게 임포트를 하고 보시면 캐릭터는 이렇게 구성되어 있다는 것을 깨달으실 겁니다. 완전히 동일하진 않지만, 보통 이런 식이죠.

마테리얼, 프리팹(모델), 텍스쳐, 애니메이션. 이죠.

저희가 직접 건드릴 부분만 말씀드려서 , 크게 나눠서 그 정도입니다.


순서대로 어떻게 사용하는지 설명해 드리도록 하죠.



먼저 프리팹. 입니다. 한마디로 설명하자면 '이게 본체'.

프로젝트 화면에서 하늘색 큐브 모양으로 나오는 녀석이 보통 프리팹입니다.

사실 프리팹 모양 옆에 흰색 종이가 나타나는 건 프리팹이라기보단 모델이지만.. 지금은 동일하게 사용 가능합니다.

쭉 드래그해서 씬 화면 위에 넣어 보세요.

어떠세요, 캐릭터가 나타났죠? Hierarchy(하이라키) 에도 오브젝트로 캐릭터가 나타납니다.


프리팹이란 이런 거에요. 한번 더 프리팹을 씬뷰 화면에 올려놓으면 하나 더 더 맵에 생기겠죠.

이렇게, 일정 설정이 모여 있는 오브젝트를 마치 블록처럼 저장해 뒀다가 사용하는 것. 그게 바로 프리팹 입니다.

그래서 설정을 할 때, 이 프리팹으로 생성한 모든 오브젝트의 설정을 만지고 싶다, 라고 생각하시면 프리팹의 옵션을 조정해주시면 됩니다.

각각의 오브젝트 옵션을 정하고 싶다면 그 오브젝트만 선택해주시면 되구요.




프리팹을 만드는 방법도 생각보다 간단합니다. 하이라키 칸의 오브젝트를 그대로 프로젝트 칸에 드래그하면 그대로 그 설정과 똑같은 프리팹 생성. 쉽죠?

오브젝트를 복사/붙여넣는 방법도 있기는 하지만, 이 방법이 저는 가장 편해 보이네요.

자, 이제 캐릭터 오브젝트에 지난번에 만들었던 Ctrl 스크립트를 PlayerCtrl로 이름만 바꿔서 넣어주죠. 알아보기 쉽게요. 플레이어를 만들어 봅시다.

이제 캐릭터는 움직일 수 있습니다. 하지만...

그냥 서있는 상태로 움직이기만 하네요.

이래서야 의미가 없죠.. 마치 공중에 떠다니는거 같습니다.

만약, 시작하자마자 움직임에 상관없이 움직이는 캐릭터가 있다면,

플레이어의 애니메이션 컴포넌트에서 Play Automatically 체크를 해제해 주시면 됩니다. 자동 시작은 할 필요가 없으니까요.


이제 애니메이션을 설명할 차례가 된 거 같네요.


애니메이션 컴포넌트가 있어야만 애니메이션을 실행 가능합니다.. 라는 것은 사실 말씀드릴 필요도 없겠죠?

 애니메이션 컴포넌트의 구성을 설명하기 위해서는, 먼저 캐릭터의 프리팹을 같이 확인해 봐야 할 것 같네요.

플레이어 캐릭터의 모델 프리팹을 누릅니다.

인스펙터에 관련된 정보가 뜨는데요, 이게 단순히 프리팹이 아니라 3D모델 프리팹일 경우엔,

이런 메뉴가 뜹니다.

모델,rig,애니메이션.

여기서 저희가 지금 주목할 부분은 애니메이션입니다.


이 메뉴에선 인스펙터 메뉴 아래쪽에 프리뷰로 애니메이션의 전체 동작을 확인하실 수 있고요, Clips 부분에서 전체 동작의 일부분을 잘라내 클립으로 만들어 둘 수 있습니다.

필요할 때 로드할수 있도록요.이렇게 잘라두면 Animation컴포넌트의 animation에 배열로 저장되게 됩니다. 나중에 코드에서 보시겠지만, 코드에서 엑세스할수 있는것도 이걸 통해서에요.



제 경우에는 애니메이션이 이미 나눠져 있네요. 앞으로 걷기, 옆으로 걷기, 뒤로, 앞으로, 그리고 보통상태로 서있는 상태.  이렇게 5개군요.

한번 코드를 만들어 볼까요?

이전에 만들었던 PlayerCtrl을 켜서, 메뉴를 추가하도록 합시다.



[System.Serializable]

//스크립트 내부의 클래스 객체에 대한 정보를, 인스펙터에 추가해 주도록 하는 기능.


public class Anims//이 애니메이션 클래스가 수정 가능하도록 인스펙터에 표시 된다.

{

//나중에 애니메이션이 바뀌거나 해도 코드수정이 필요없도록 변수에 애니메이션 저장해서 움직임.

public AnimationClip idle;

public AnimationClip runForward;

public AnimationClip runBackward;

public AnimationClip runRight;

public AnimationClip runLeft;

//public AnimationClip die [3]; 처럼 애니메이션도 배열로 만들 수 있다.


}


첫 부분입니다. 원래 스크립트 내에서 따로 클래스를 추가하면 그 클래스는 인스펙터에서 보이지가 않습니다. 그러나 [System.Serializable] 이걸 붙여 주시면, 다음에 나오는 그림처럼

설정이 가능하지요.







public class PlayerCtrl : MonoBehaviour 

{

public float moveSpeed = 5.0f;

public float moveRot = 0.5f;

public Anims anims;


private Transform tr = null;

private Animation anim = null;


이전에서 추가된 부분만 bold 표시 해 두었습니다. 확인 되시나요?

위쪽에 미리 만든 애니메이션 클래스의 인스턴스, anims를 하나 만듭니다.

그리고 애니메이션 컴포넌트를 가져올 애니메이션 클래스, anim도 만들죠.



void Start()//start라는 함수 있으니 주의

{

tr = this.gameObject.GetComponent<Transform> ();

anim = GetComponent<Animation> ();

anim.clip = anims.idle;

anim.Play ();

}


전과 마찬가지로 컴포넌트를 받아서, 그 컴포넌트에 접근할 수 있도록 해줍니다.

그 후 처음으로 실행하는 거니, 기본으로 서있는 애니메이션을 호출해 줍니다.

이제 void Update()안쪽을 살펴봅시다.


float v = Input.GetAxis ("Vertical");  //-1.0f~0.0f~1.0f

float h = Input.GetAxis ("Horizontal"); //-1.0f~0.0f~1.0f




if (v >= 0.1f && v*v>h*h) {//조건. 앞으로 가고 있으며, 옆으로 가는 속도보다 앞으로 가는 속도가 빠르다.

anim.CrossFade (anims.runForward.name, 0.3f);

}

else if (v <= -0.1f&& v*v>h*h) {

anim.CrossFade (anims.runBackward.name, 0.3f);

}


else if (h >= 0.1f&& v*v<h*h) {

anim.CrossFade (anims.runRight.name, 0.3f);

}

else if (h <= -0.1f&& v*v<h*h) {

anim.CrossFade (anims.runLeft.name, 0.3f);

}

else if (v >= 0.1f) {//조건. 앞으로 가고 있으며, 옆으로 가는 속도보다 앞으로 가는 속도가 빠르다.

anim.CrossFade (anims.runForward.name, 0.3f);

}

else if (v <= -0.1f) {

anim.CrossFade (anims.runBackward.name, 0.3f);

}

else if(h==0.0f && v==0.0f) {

anim.CrossFade (anims.idle.name, 0.3f);

}


업데이트 함수에는 이 부분을 추가해 줍니다. 조건은 자세히 읽어보면 아실 거에요. 예외가 없도록 짜 줍시다.

CrossFade는 결국 이전 애니메이션에서 새 애니메이션으로 넘어가는 함수인 겁니다.

CrossFade (애니메이션 클립명, 시간);


수정을 마치고, 플레이어 캐릭터의 인스펙터 화면에서 캐릭터의 애니메이션을 드래그&드롭으로 저희가 설정한 클래스의 변수에다가 올려놓아 주세요.

애니메이션이 연결됩니다. 그리고 실행하면..



어떠신가요, 잘 되시나요?


그러시다면 오늘의 가장 힘든 부분은 끝났습니다. 다행이네요.


이제 여담 삼아 캐릭터의 외모에 좀더 신경쓰는 법을 말씀드릴게요.

일단 일반적인 방법.

우선 Mesh Renderer 라는 컴포넌트가 붙어 있는, 그러니까 캐릭터의 그림을 그려 주는 속성이 있는 부분은 찾아 주세요. 저 같은 경우, 여기에 있군요. 




만약 아예 렌더링이 안되는 캐릭터로 진행하고 계시다면 컴포넌트 추가에서

메시 렌더러를 추가해 주시는 것도 좋습니다.

skined mesh renderer를 컴포넌트에 추가해 줍니다.



그렇게 해결하고 나면, 머티리얼이라는 컴포넌트가 자동으로 생깁니다.

머티리얼은 렌더링을 하기 위한 재료인데요. 직접 그려 주는거죠.

옵션을 확인해 볼까요?




보통 저희가 건드릴 옵션은 이 두가지입니다.

기본적인 그림과, 노말 맵이라는 그림에 굴곡을 표현해 주는 특수한 그림이죠. 입체감을 좀더 살리기 위해서요.



이부분을 적용해 주시면, 쨘!

스킨이 잘 적용되었습니다.

다음 리뷰부터는 좀더 멋진 캐릭터로 진행할 수 있겠군요.

그럼 모두들 다음 시간에 만나도록 해요, 안녕히 계세요~! (_ _   )