애니메이터 컨트롤러 동작 변경 문제

 

이전까지 게임을 제작을 시작할 때, 5.3.5 버전의 유니티를 사용하다가, 변경된 파티클 시스템을 사용하기 위해 유니티를 5.6.0으로 업데이트를 진행했었다. 엔진을 업데이트하면서 변경점으로 인해서 프로젝트에 어느 정도 문제가 발생할 것이라고 생각은 하고 있었지만, 예상외로 별다른 문제없이 유니티 업데이트가 진행되었었다.

 

문제는 애니메이션 쪽에서 발생했다. 제작 중인 게임은 최적화를 위해서 오브젝트 풀링(Object pooling) 기법을 사용하고 있었는데, 이 기법을 간단하게 설명하자면 유니티 상에서 게임 오브젝트를 생성(Instantiate)하고 삭제(Destory)하는 과정에서 발생하는 부하를 줄이기 위해, 게임에 필요한 게임 오브젝트를 미리 생성해서 컨테이너에 저장해두고, 필요하면 게임 오브젝트의 활성화해서 사용하고 죽음이나 파괴 등으로 필요없어진 게임 오브젝트의 비활성화 시키는 방법으로 비활성화 시킨 오브젝트라도 같은 종류의 오브젝트가 필요하면 다시 활성화 시켜서 재활용할 수 있다. 이렇게 하면 빠르게 작동해야하는 게임 도중에 무거운 Instantiate() 함수의 호출이나 이후에 가비지 컬렉터(Gabage Collector) 호출로 이어지는 Destory() 함수의 호출을 최소화할 수 있다.

 

이 오브젝트 풀링 기법과 유니티가 버전업되면서 변경된 애니메이터 컨트롤러의 동작이 만나면서 문제가 발생했다. 이전에 사용하던 5.3.5의 애니메이터 컨트롤러의 경우에는 동작중이던 게임오브젝트를 비활성화 시키고 난 이후에 해당 오브젝트를 재사용하기 위해서 다시 활성화 시키면 애니메이터 컨트롤러의 상태가 초기로 자동으로 돌아갔다.

 

 

그렇기 때문에 애니메이터를 위의 그림과 같이 구성해두면 캐릭터가 사망하면서 Die 트리거가 작동해서 Die 애니메이션이 작동한 이후에 죽은 캐릭터의 게임 오브젝트를 비활성화 시키고, 나중에 이 오브젝트를 재사용하기 위해 다시 활성화 시키면 애니메이터 컨트롤러의 상태는 자동으로 Idle 상태로 돌아오는 방식으로 동작했었다.

 

하지만 유니티를 5.6.0으로 업데이트한 이후에는 게임 오브젝트를 비활성화 시켰다가 다시 활성화 시키면 애니메이터 컨트롤러의 상태가 처음으로 돌아오지 않고 비활성화 시키던 당시의 상태를 유지하는 것으로 애니메이터 컨트롤러의 동작이 변경되었다(5.3.5와 5.6.0 사이의 어느 버전에서 동작이 변경되었을 것이다. 정확한 릴리즈 노트를 찾아보지는 않아서 변경된 정확한 버전은 알지 못한다).

 

그렇기 때문에 죽은 캐릭터의 게임 오브젝트를 재활용하려고 게임 오브젝트를 다시 활성화 시키면 Die 애니메이션이 끝난 상태로 나타나는 버그가 발생하게 되었다.

 

이러한 문제해결하기 위해서는 애니메이터 컨트롤러에서 상태 노드들의 연결을 약간 변경해 주어야 했다.

 

 

애니메이션이 종료된 이후에 제일 처음의 상태로 돌아가야 한다면 위의 그림처럼 그 상태는 반드시 Exit 노드로 연결되어야 한다. 애니메이션의 상태를 Exit 노드와 연결해 주면 그 애니메이션이 끝난 이후에 Exit 노드로 이동한 후 다시 Entry로 돌아가서 제일 처음 애니메이션을 다시 출력한다. 하지만 Die 같은 애니메이션의 경우 아무런 제약 없이 Exit 노드와 연결해주면 캐릭터가 죽어서 넘어진 다음에 다시 벌떡 일어나는 불상사가 발생할 수도 있다. 그런 종류의 불상사를 막아야 하는 경우에는 Exit 노드로 가는 트랜지션(Transition)에 하나의 트리거를 추가해 준 다음, 다시 돌아갈 상황이 되었을 때, 스크립트에서 트리거를 호출해서 애니메이션 상태를 처음으로 돌릴 수 있다.

 

결론적으로 최신 버전의 유니티에서는 애니메이터 컨트롤러가 끊임없이 흘러가게 하기 위해서는 마지막 애니메이션을 절대로 고립된 상태로 두지말고 Exit 노드에 연결해 주어야 한다.

 

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

유니티 애니메이션 레이어(Animation Layer) 사용하기

 

 

 

지난 애니메이션 섹션에서는 비슷하지만 방향성이 다른 동작, 혹은 비슷하지만 속도가 다른 동작을 섞는데 사용하는 애니메이션 블랜드(Animation Blend)에 대해서 이야기해 보았다. 이번 섹션에서는 애니메이션 위에 일정 부분에 애니메이션을 덮어씌우는 애니메이션 레이어(Animation Layer)에 대해서 배울 것이다.

 

지난 애니메이션 블랜드 섹션 :: http://wergia.tistory.com/54

 

애니메이션 레이어는 여러 종류의 게임에서 이용될 수 있지만, 대표적으로는 FPS나 TPS 형식의 게임에서 주로 이용될 수 있다. 이러한 형식의 게임의 경우 캐릭터는 한 순간에 한 가지 행동만을 하는 것이 아니라, 하나 이상, 일반적으로는 두 개 정도의 행동을 하는 일이 많다. 간단하게 예를 들자면 총 같은 화기를 사용하는 FPS 게임이라면 캐릭터는 달리거나 걷는 동시에 총을 쏠 수도 있고, 단검을 휘두를 수도 있으며, 탄창을 교체하기도 한다. 앞서 이야기한 행동들을 하기 위해서 걸음을 멈추는 경우는 거의 없다. 평소에는 상체와 하체 모두 달리는 애니메이션을 취하지만, 달리는 도중에 다른 행동을 취한다면 하체는 여전히 달리는 모션을 출력하지만, 상체는 총을 쏘거나, 단검을 휘두르거나, 탄창을 교체하는 애니메이션을 출력하게 되는 것이다.

 

물론 이러한 애니메이션들을 일일이 만들어 내는 방법도 있지만 이것은 너무 비효율적인 일이다. 만약에 애니메이션 레이어를 사용하지 않고 모든 애니메이션을 만든다면, 가만히 서서 위의 세 가지 행동을 하는 애니메이션, 걸으면서 다른 행동을 하는 애니메이션, 달리면서 행동을 하는 애니메이션 등을 모두 만들어내야 할 뿐만 아니라, 만약 점프하면서 폭탄을 던지는 모션을 만들고자 한다면 점프하는 모션 중 어느 타이밍에 폭탄을 던지는 모션을 추가해야할지 골머리를 앓게 될 것이다.

 

하지만 애니메이션 레이어를 사용하게 된다면, 걷는 애니메이션, 달리는 애니메이션, 서있는 애니메이션, 점프 애니메이션, 그리고 각각의 행동을 취하는 애니메이션 정도만 만든다면 위에서 설명한 표현들을 손쉽게 할 수 있게 된다.

 

 

이번 예시를 들기 위해서 지난 애니메이션 블랜드 섹션에서 사용했던 달리기 모션과 함께 이번에 간단하게 만든 팔을 휘두르는 애니메이션을 사용할 것이다. 공격이라고 보기엔 귀엽지만 공격 모션이다. 애니메이션 레이어와 달리는 모션, 그리고 가만히 서서 공격하는 모션만 있다면 달리면서 공격하는 모션을 만들 수 있다.

 

애니메이션 레이어 사용법을 배우기 위해 다음의 튜토리얼을 따라해보도록 하자.

 

 

 

1. 애니메이션 레이어에 사용할 Animator Controller를 생성하고 그 이름을 Animation Layer라고 짓도록 하자.

 

 

2. 생성한 애니메이터 컨트롤러를 열면 다음과 같이 빈 애니메이터 컨트롤러 창이 보일 것인데 그 중에 Layers라는 항목이 있을 것이다. 그 항목을 선택하면 Base Layer가 있는데 이 레이어는 애니메이션에서 기본적으로 제공하는 레이어이다. 이 레이어의 이름을 바꿀 수도 있고 나중에 다른 레이어를 추가한다면 기본 레이어를 삭제할 수도 있다.

 

3. 기본적인 달리기 애니메이션을 애니메이터 컨트롤러에 추가한다. 그리고 이 애니메이터 컨트롤러를 씬에 추가한 캐릭터의 애니메이터 컴포넌트에 넣고 플레이 버튼을 누르면 이 박스맨은 계속해서 달리기만 할 것이다.

 

4. 이 다음 작업은 아바타 마스크(Avatar Mask)를 생성하는 것이다. 이 아바타 마스크는 애니메이션 레이어를 사용할 때, 위에 덮어쓴 애니메이션이 적용될 본을 지정하는 것으로, 해당 레이어에서 원하는 본만 애니메이션이 작동하고 그 외의 본은 그 아래 레이어의 애니메이션을 작동하도록 만드는 것이다.

 

5. 생성한 아바타 마스크를 열어보면 Humanoid 방식과 Transform 방식이 있는 것을 알 수 있다. 휴머노이드 방식의 경우는 사진을 보면 알다시피 일반적인 사람형태의 본에 대해서 손쉽게 마스크를 지정할 수 있게 하는 것이고, 트랜스폼 방식은 직접 만든 특별한 형태의 본을 가져와서 원하는 애니메이션이 적용될 본을 직접 선택하는 방식이다.

 

6. 이번엔 None이라고 비어있는 Avatar 란에 직접 만든 박스맨의 본을 가져와야 한다. 이 본은 BoxMan@Attack을 열어보면 목각인형 상체 모양의 BoxMan@AttackAvatar를 볼 수 있는데 이것을 끌어와서 넣어주면 된다. 그리고 Import skeleton 버튼을 클릭하면 박스맨에 적용된 본들이 아바타 마스크의 인스펙터 창에 표시된다.

 

7. 이번 섹션의 작업에서 우리가 동작하기 바라는 것은 왼팔 하나뿐이다. 박스맨의 본들 중에 왼팔에 해당하는 본은 Bone005(mirrored)이다. 이 본만이 움직이길 원하기 때문에 Bone005(mirrored)를 제외한 모든 본의 체크를 꺼준다.

 

8. 이제 아까 만든 AnimationLayer 애니메이터 컨트롤러로 돌아와서 Layers 항목의 아래 쪽에 +버튼을 클릭하여 새 레이어를 만들고 그 이름을 UpperBody로 변경한다.

 

9. 잠시 Parameters 항목으로 넘어가서 애니메이터 컨트롤러의 매개변수에 "Attack"라는 이름의 트리거를 생성한다.

 

10. UpperBody 레이어에 NoneAttack 상태를 만들고 애니메이션은 비워둔다. 아무것도 하지 않는 동작이기 때문에 비워두는 것이다. 만약 아무것도 하지 않는 동작이기 때문에 아래쪽의 베이스 레이어와 맞춰서 달리는 동작으로 해줘야 한다고 생각할 수 있는데 그런 식으로 달리는 애니메이션을 넣었다가는 하체의 달리는 모션과 상체의 팔 휘두르는 모션의 싱크가 일치하지 않게되는 현상을 겪을 수도 있다.

 

11. Attack 상태를 추가하고 Attack 애니메이션을 넣어준 다음에 NoneAttack 상태에서 Attack 상태로 넘어가는 조건에 아까 만든 Attack 트리거를 넣어준다. 이렇게 함으로서 이제 애니메이션 컨트롤러에 Attack 트리거 신호가 들어오면 캐릭터는 어택 모션을 취하게 될 것이다(설정에 실수를 했는데 Inspector 창에서 Has Exit Time의 체크는 해제해야 한다).

 

12. 다음 작업은 레이어 설정을 해주는 것이다. 레이어 이름 옆에 톱니바퀴 버튼을 클릭하면 레이어 옵션을 볼 수 있는데 여기서 두 가지를 설정해주면 된다. 첫 번째는 Weight 값인데 이 값은 현재 레이어와 아래 레이어의 애니메이션 비중을 의미한다. 1에 가까울 수록 캐릭터는 현재 레이어에 가까운 모션을 취한다. 즉, 1값이면 캐릭터는 현재 레이어의 애니메이션만 취한다. 그리고 Mask 옵션인데 이것은 애니메이션을 출력하고자 하는 부위만 출력하도록 해주는 것이다. 아까 전에 만든 왼팔만 적용되는 마스크를 넣어준다.

 

애니메이션 레이어에 필요한 모든 설정을 끝냈다. 이제 플레이 버튼을 클릭하고 캐릭터의 달리는 모션이 출력되는 도중에 Attack 트리거를 켜보면 다음 이미지와 같이 박스맨 캐릭터가 달리기 모션을 취하면서도 왼팔만은 정상적으로 휘두르는 것을 볼 수 있다.

 

 

 

 

이것처럼 애니메이션 레이어를 사용하면 애니메이션 작업양을 획기적으로 줄이면서도 다양한 동작을 취하도록 할 수 있다. 하지만 이 예시는 매우 간단하게 제작된 본과 모델링을 사용하는 것으로, 일반적으로 게임 제작에 사용되는 복잡한 형태의 본과 모델을 사용하는 경우에는 본의 구조나 리깅된 면의 정상적인 움직임을 위한 면밀한 연구가 필요할 것이다.

 

마지막으로 다음의 링크에서 위의 예시로 제작된 간단한 애니메이션 레이어 예제를 받을 수 있다.

 

AnimaitonLayerExample.zip
다운로드

 

 

 

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

유니티에서 애니메이션 블랜드 사용하기

 

작성 기준 버전 :: 5.6 - 2019.4

 

[이 포스트의 내용은 유튜브 영상으로도 시청하실 수 있습니다]

 

게임에서 자연스러운 애니메이션은, 캐릭터에 생명을 불어넣어 주는 요소 중에 하나이다. 다양한 종류의 애니메이션을 제작하면 캐릭터의 움직임은 더욱 자연스러워 질 것이다. 예를 들어 캐릭터가 움직이는 방향에 따라서 정면으로 움직일 때는 바르게 걷고 정면을 본체로 왼쪽으로 움직이면 왼쪽으로 옆걸음을 하는 방식으로 제작한다면 만약 왼쪽 정면 대각선 방향을 향해서 이동하면 어색한 움직임을 보일 것이다. 그것을 자연스럽게 처리하려면 왼쪽 정면 대각선 방향으로 움직이는 애니메이션을 만들어주어야 하고, 또 거기서 더 자연스러운 애니메이션을 만들고자 한다면 그 정면과 왼쪽 정면 대각선 사이, 왼쪽과 왼쪽 정면 대각선 사이의 애니메이션을 만들어서 추가해주어야 하는 것이다. 하지만 그렇다고 해서 게임 제작자가 모든 경우의 애니메이션을 일일이 다 만들 수는 없다. 그런 작업은 쉽지 않을 뿐만 아니라 게임제작에 들어가는 자원과 시간이 부족하다.

 

이러한 문제를 해결하기 위해서 사용되는 기능이 바로 애니메이션 블랜드이다.

 

이번 예시를 설명하기 위해 간단한 박스맨을 제작했고, 걷기 모션과 달리기 모션을 만들었다. 이동속도에 따른 걷기/달리기 애니메이션 블랜드는 가장 대표적이고 유용한 예제이다. 캐릭터의 이동 속도에 따라서 캐릭터의 보폭이나 발걸음 이동속도 역시 유동적으로 변하는 편이 자연스럽게 보일 것이다.

 

 

 

간단하게 걷는 모션과 달리는 모션의 차이를 주기 위해서 걷는 모션은 팔다리를 가볍게 움직이고 달리는 모션은 팔다리를 격하게 흔들도록 만들어 보았다.

 

 

 

애니메이션 블랜드를 사용하기 위해서는 우선 캐릭터의 애니메이션을 관리할 애니메이터 컨트롤러(Animator Controller)를 생성해야 한다.

 

 

애니메이터를 생성해서 열어보면 텅 빈 애니메이터 화면이 보일 것이다.

 

 

빈 화면에 우클릭해서 Create State > From New Blend Tree 항목을 선택하면 다음과 같이 Blend Tree라는 이름의 애니메이션 스테이트가 생성되고 Parameters에는 Blend라는 이름의 float 형식의 매개변수가 생성될 것이다 :

 

 

이 Blend라는 이름의 매개변수는 애니메이션 블랜드에서 두 여러 애니메이션이 섞일 때, 어느 애니메이션으로 치우쳐서 출력될 것인지를 결정하는데 도움을 줄 것이다. 현재는 캐릭터의 이동 모션에 따라 걷기/달리기 모션 블랜드를 할 것이기 때문에 이 변수의 이름을 "MoveSpeed"로 변경하도록 하자.

 

 

그리고 애니메이터 창에서 Blend Tree 스테이트를 더블 클릭해보면 다음과 같이 블랜드 트리로 내려가게 될 것이다.

 

 

위의 그림에서처럼 블랜드 트리를 선택하고 인스펙터 창(Inspector View)을 보면 Blend Type과 Parameter 그리고 Motion을 볼 수 있다. 우선 블랜드 타입은 파라메타의 변화에 따라서 어떻게 애니메이션이 블랜드 될 것인지를 정하는 것이다. 그리고 파라메터는 현재 애니메이션의 파라메터 중에 이 블랜드 트리에서 사용할 값을 정하는 것이며, 모션은 이 블랜드 트리에서 섞을 애니메이션을 정하는 것이다.

 

 

지금은 이동 속도의 변화에 따라서 모션을 블랜드할 것이기 때문에 가만히 정지 > 걷기 > 달리기 이 세 가지 모션을 추가하겠다. 모션 밑에 있는 + 버튼을 누르고 Add Motion Field 항목을 선택하면 다음과 같이 화면이 변한다. 이제 모션들을 추가해보자.

 

 

각 모션에 애니메이션들을 추가해주면 위의 그림처럼 각 애니메이션 노드가 생성되서 블랜드 트리와 연결되는 것을 볼 수 있다. 여기서 또 조정할 수 있는 옵션은 Threshold이다. Threshold는 한계점이나 역치라는 의미로 여기서는 각 애니메이션의 그래프 상의 위치를 의미한다. 위의 그림에서는 Stand의 Threshold는 0, Walk의 threshold는 0.5, Run의 threshold는 1이다. 이 의미는 MoveSpeed의 값이 0~1사이에서만 움직일 것이고 0~0.5 값이면 Stand와 Walk 모션이 블랜드가 되고 0.5~1 값이면 Walk와 Run 모션이 블랜드된다는 것이다. 하지만 일반적으로 게임에서는 이동 속도 값을 0~1로 사용하지 않기 때문에 그럴 때는 Automate Thresholds 체크를 풀어주면 값을 적절하게 조절해줄 수 있게 된다.

 

만약에 최대 이동 속도가 50이고 걷는 속도가 10이라고 한다면 그 값을 아래와 같이 입력해주면 된다. 이렇게 설정해주고 캐릭터의 스크립트에서 이동 모션을 출력하면서 이동 속도에 따라서 animator.SetFloat("MoveSpeed", moveSpeed);를 호출해주면 애니메이터는 자동으로 변화하는 이동 속도에 따라 어느 애니메이션들을 얼마나 출력할지 결정하고 출력해줄 것이다.

 

 

 

 

애니메이션 블랜드를 사용할 때, 주의할 점은 블랜드된 애니메이션이 자연스럽게 보이기 위해서는 블랜드 되는 모션들이 비슷한 동작을 취해야하고 타이밍이 비슷해야 한다는 것이다. 하지만 예외적으로 애니메이션의 길이가 다른 것은 블랜드의 결과에 영향을 미치지 않는다. 그 이유는 정확한 블랜드를 위해서 두 애니메이션의 길이를 똑같게 맞추는 정규화 작업을 한 이후에 블랜드를 하기 때문이다.

 

간단한 위의 예제는 다음 링크에서 다운로드 받아서 실행해볼 수 있다.

 

AnimationBlendPractice.zip
다운로드

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

유니티에서 XML 사용하기

 

게임을 제작할 때에, 여러 가지 데이터들을 저장하고 불러와야하는 경우가 많다. 게임 진행 상황을 저장하는 경우도 있을 수 있고, 맵이 랜덤으로 생성되는 게임의 경우에는 현재 생성된 맵의 데이터를 저장해뒀다가 다음에 다시 불러와야 할 수도 있다. 또는 게임의 아이템 정보들의 목록을 저장해둬야 할 수도 있다. 위와 같은 경우에 XML을 사용하면 저런 기능들을 쉽게 구현할 수 있게 된다.

 

XML은 마크업 언어를 정의하기 위한 확장성 마크업 언어라고 하는데, 여기서는 조작하기 쉬운 일종의 로컬 데이터베이스나 데이터를 저장하기 위한 파일로 사용될 것이다.

 

이번 섹션의 예시에서는 게임의 캐릭터 정보를 저장하기 위해서 XML을 사용한다고 가정하고 진행 해보겠다.

 

1. XML 파일 생성하여 저장하기

첫 번째로 알아볼 것은 XML 파일을 생성하는 것이다. 만약 게임을 시작하고 처음으로 저장을 하는 경우라면 아직 데이터를 저장하기 위한 파일이 생성되어 있지 않을 것이다. 물론 미리 XML 파일을 만들어두고 사용하는 것도 가능하지만, XML 파일을 생성하는 법에 대해서 알아두는 것도 나쁘지 않다.

 

다음이 XML을 생성하여 저장하는 코드의 전체이다 :

 

public class XmlTest : MonoBehaviour
{
    void Start()
    {
        CreateXml();
    }

    void CreateXml()
    {
        XmlDocument xmlDoc = new XmlDocument();

        // Xml을 선언한다(xml의 버전과 인코딩 방식을 정해준다.)
        xmlDoc.AppendChild(xmlDoc.CreateXmlDeclaration("1.0", "utf-8", "yes"));

        // 루트 노드 생성
        XmlNode root = xmlDoc.CreateNode(XmlNodeType.Element, "CharacterInfo", string.Empty);
        xmlDoc.AppendChild(root);

        // 자식 노드 생성
        XmlNode child = xmlDoc.CreateNode(XmlNodeType.Element, "Character", string.Empty);
        root.AppendChild(child);

        // 자식 노드에 들어갈 속성 생성
        XmlElement name = xmlDoc.CreateElement("Name");
        name.InnerText = "wergia";
        child.AppendChild(name);

        XmlElement lv = xmlDoc.CreateElement("Level");
        lv.InnerText = "1";
        child.AppendChild(lv);

        XmlElement exp = xmlDoc.CreateElement("Experience");
        exp.InnerText = "45";
        child.AppendChild(exp);

        xmlDoc.Save("./Assets/Resources/Character.xml");
    }
}

 

저장할 캐릭터 데이터의 내용은 캐릭터의 이름과 레벨, 경험치라고 가정하고 진행했다. 위의 코드를 실행하면 지정된 경로에 Character.xml 파일이 생성된다.

 

 

생성된 xml 파일은 다음과 같은 내용이다 :

 

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<CharacterInfo>
  <Character>
    <Name>wergia</Name>
    <Level>1</Level>
    <Experience>45</Experience>
  </Character>
</CharacterInfo>

 

작성한 대로 캐릭터의 이름, 레벨, 경험치 값이 저장되었다.

 

 

2. XML 파일에서 데이터 불러와서 사용하기

데이터를 저장하는데 성공했다면 이 다음에는 저장된 데이터를 불러와서 사용해야할 것이다. 다음의 코드가 저장된 XML 데이터를 불러오는 것이다.

 

using System.Xml;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class XmlTest : MonoBehaviour
{
    void Start()
    {
        LoadXml();
    }

    void LoadXml()
    {
        TextAsset textAsset = (TextAsset)Resources.Load("Character");
        Debug.Log(textAsset);
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.LoadXml(textAsset.text);

        XmlNodeList nodes = xmlDoc.SelectNodes("CharacterInfo/Character");

        foreach (XmlNode node in nodes)
        {
            Debug.Log("Name :: " + node.SelectSingleNode("Name").InnerText);
            Debug.Log("Level :: " + node.SelectSingleNode("Level").InnerText);
            Debug.Log("Exp :: " + node.SelectSingleNode("Experience").InnerText);
        }
    }

}

 

위의 코드를 실행해보면 XML에 저장해둔 캐릭터 데이터가 잘 불러와졌음을 알 수 있다.

 

 

불러온 데이터를 캐릭터 오브젝트를 생성해서 그 값을 다시 넣어준다면 캐릭터는 저장되기 직전의 캐릭터와 같은 상태를 가지게 될 것이다.

 

 

3. 이미 존재하는 XML 파일에 데이터 덮어씌워 저장하기

게임에서 이미 저장하기 기능을 사용해서 XML 파일이 생성되어 있고, 그 XML파일에 덮어 씌워 저장하는 경우도 있을 수 있다. 그럴 땐 다음 코드와 같이 이미 존재하는 XML 파일을 불러온 후에 그 안의 값을 수정하고 저장해주면 된다 :

 

using System.Xml;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class XmlTest : MonoBehaviour
{
    void Start()
    {
        SaveOverlapXml();
    }

    void SaveOverlapXml()
    {
        TextAsset textAsset = (TextAsset)Resources.Load("Character");
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.LoadXml(textAsset.text);

        XmlNodeList nodes = xmlDoc.SelectNodes("CharacterInfo/Character");
        XmlNode character = nodes[0];

        character.SelectSingleNode("Name").InnerText = "wergia";
        character.SelectSingleNode("Level").InnerText = "5";
        character.SelectSingleNode("Experience").InnerText = "180";

        xmlDoc.Save("./Assets/Resources/Character.xml");
    }

}

 

위 코드를 실행해보면 다음과 같이 XML 파일이 변경되어 있는 것을 볼 수 있다 :

 

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<CharacterInfo>
  <Character>
    <Name>wergia</Name>
    <Level>5</Level>
    <Experience>180</Experience>
  </Character>
</CharacterInfo>

 

위의 예시처럼 덮어씌워 저장하는 방법 이외에도 새로 노드를 덧붙여서 추가적인 내용을 저장한다던가, 아니면 여러 개의 저장 슬롯을 만들어서 저장하는 방법을 사용할 수 있다.

 

 

4. 취약점

저장 방식으로 사용하기 굉장히 편리한 XML이지만 이것도 굉장한 단점이 하나 있다. 이 XML을 그대로 사용하면 그냥 텍스트 편집기로도 열리기 때문에 사용자들이 쉽게 그 값을 변조할 수 있게 된다. 이것은 하나의 에디터나 다름없는 것이기 때문에 만약 제작하는 게임이 데이터가 변조되면 안되는 경우에는 심각한 문제가 될 수 있다. 만약 XML에 게임 데이터를 저장하고 불러와야 되는 경우에는 별도의 암호화/복호화 기능을 덧붙여서 기능을 만드는 것을 추천한다.

 

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

유니티에서 파이어베이스 인증(Auth) 기능 이용하기

 

 

 

네트워크 게임을 제작할 때, 중요한 부분 중의 하나가 회원가입, 로그인, 로그아웃 등의 기능을 제공하는 것이다. 이 인증 기능들을 제공하고 관리하는 것을 직접 구현하기 위해서는 해야할 일이 많다. 회원들의 목록과 정보를 관리하는 데이터베이스도 만들어야 하고 서버에 유저들이 회원가입이 로그인을 위해서 입력한 정보를 보내고 그 결과를 돌려주는 기능들 역시 직접 구현해야만 한다. 하지만 구글의 파이어베이스에서는 사용자들이 필요로 하는 기능들을 이미 제공하고 있다.

 

지난 섹션에서 우리는 파이어베이스에서 테스트 프로젝트를 생성하고 유니티와 연결하는 작업을 진행했다. 이번 섹션의 예시는 지난 섹션 이후에서 부터 시작하도록 하겠다.

 

 

파이어베이스 시작하기로 제일 첫 화면으로 들어가면 지난 섹션에서 만든 테스트 프로젝트가 보일 것이다. 그 프로젝트를 선택하면 해당 프로젝트의 설정가능한 기능들의 목록을 볼 수 있다.

 

 

이 중에서 우리가 사용할 기능을 Authentication(인증)이다. 이 기능을 이용하면 별도의 회원정보를 위한 데이터베이스 구축이나 기능 구현없이 회원가입, 로그인, 로그아웃 등의 기능을 만들 수 있다. 이 authentication 메뉴를 선택해서 들어가보면 다음과 같은 화면을 볼 수 있다.

 

 

사용자 탭에서는 현재 제공하는 프로젝트에 가입된 사용자들의 목록을 보여주는데 현재는 가입된 유저가 없기 때문에 아무런 사용자도 나오지 않는다.

 

 

그 옆의 로그인 방법 탭에서는 로그인에 사용할 방법들을 설정할 수 있다. 단순하게 이메일과 비밀번호를 이용해서 로그인 하는 방법도 제공하지만 구글 아이디나 페이스북, 트위터등의 아이디를 통해서도 가입이 가능하도록 기능을 제공하고 있다. 현재는 프로젝트가 처음으로 만들어졌기 때문에 모든 로그인 방법에 대해서 "중지됨"이라고 표시되어 있다. 이번 섹션의 예제에서는 이메일을 통한 로그인 방법을 사용해보겠다.

 

 

이메일/비밀번호 항목을 선택해서 사용설정을 켜주고 저장한다. 다만 이 부분에서 주의할 점이 하나 있다. 파이어베이스 프로젝트에서 기능 옵션을 변경하였다면 google-services.json 파일의 내용이 유니티 프로젝트에 넣어줬던 파일과 다르게 변경되기 때문에 새롭게 다운받아서 넣어주어야 한다는 것이다. 그렇게 하지 않는다면 기존의 google-services.json 파일을 사용하고 있는 프로젝트는 변경된 파이어베이스 서버에 제대로 접속할 수 없게 된다.

 

파이어베이스 프로젝트의 기능 옵션을 변경해서 google-services.json 파일을 새로 다운로드 받아야 한다면 다음의 경로를 따르면 된다.

 

 

그 다음의 작업은 유니티 프로젝트에서 이루어질 것이다. 이전 섹션에서 걸어줬던 작업에 필요한 파이어베이스 유니티 SDK를 다운로드 받을 수 있는 링크를 다시 걸겠다.

 

https://firebase.google.com/docs/unity/setup

 

다운로드 받은 SDK의 압축을 풀어보면 필요한 SDK들이 기능별로 유니티 패키지로 묶어있는 것을 볼 수 있다. 우리는 이 중에서 FirebaseAuth.unitypackage를 유니티 프로젝트에 임포트해야 한다.

 

 

유니티 에디터의 프로젝트 뷰에서 우클릭한 이후에 Import Package > Custom Package를 선택한다.

 

 

아까 받은 SDK 중에서 FirebaseAuth.unitypackage를 임포트한다.

 

 

필요한 SDK를 임포트하고 나면 프로젝트 창이 다음처럼 될 것이다.

 

 

이렇게 되면 파이어베이스의 인증 기능을 사용하기 위한 준비가 모두 끝난 것이다.

 

 

1. 회원가입기능 만들기

우선은 이메일과 비밀번호를 이용한 회원가입 기능을 제작해보겠다. 다음과 같이 UGUI를 이용해서 화면을 구성해보자.

 

 

이메일과 비밀번호를 입력할 수 있는 InputField와 회원가입, 로그인을 할 수 있는 버튼과 마지막에 결과를 알려줄 텍스트를 만들었다. 다음 과정은 인증 과정을 관리할 오브젝트를 만드는 것이다. 씬에 AuthObject를 만들고 그 오브젝트에 FirebaseManager라는 스크립트를 만들어서 붙여준다.

 

 

FirebaseManager의 코드 내용은 다음과 같다 :

 

using UnityEngine;
using UnityEngine.UI;

public class FirebaseManager : MonoBehaviour
{
    // 이메일 InputField
    [SerializeField]
    InputField emailInput;
    // 비밀번호 InputField
    [SerializeField]
    InputField passInput;
    // 결과를 알려줄 텍스트
    [SerializeField]
    Text resultText;

    // 인증을 관리할 객체
    Firebase.Auth.FirebaseAuth auth;

    // Use this for initialization
    void Awake ()
    {
        // 인증을 관리할 객체를 초기화 한다.
        auth = Firebase.Auth.FirebaseAuth.DefaultInstance;
    }
   
    // 회원가입 버튼을 눌렀을 때 작동할 함수
    public void SignUp()
    {
        // 회원가입 버튼은 인풋 필드가 비어있지 않을 때 작동한다.
        if(emailInput.text.Length != 0 && passInput.text.Length != 0)
        {
            auth.CreateUserWithEmailAndPasswordAsync(emailInput.text, passInput.text).ContinueWith(
                task =>
                {
                    if(!task.IsCanceled && !task.IsFaulted)
                    {
                        resultText.text = "회원가입 성공";
                    }
                    else
                    {
                        resultText.text = "회원가입 실패";
                    }
                });
        }
    }

    // 로그인 버튼을 눌렀을 때 작동할 함수
    public void SignIn()
    {
        // 로그인 버튼은 인풋 필드가 비어있지 않을 때 작동한다.
        if (emailInput.text.Length != 0 && passInput.text.Length != 0)
        {
            auth.SignInWithEmailAndPasswordAsync(emailInput.text, passInput.text).ContinueWith(
                task =>
                {
                    if (task.IsCompleted && !task.IsCanceled && !task.IsFaulted)
                    {
                        Firebase.Auth.FirebaseUser newUser = task.Result;
                        resultText.text = "로그인 성공";
                    }
                    else
                    {
                        resultText.text = "로그인 실패";
                    }
                });
        }
    }
}

 

코드의 작성을 마쳤다면 유니티 에디터의 오브젝트에 필요한 오브젝트를 넣어주어야 한다. FirebaseManager에는 각 Input Field와 결과 텍스트를 넣어주고 회원가입 버튼과 로그인 버튼의 OnClick 이벤트에 AuthObject를 끼워넣고 각자 호출해야하는 함수를 설정해주어야 한다.

 

 

이상으로 유니티에서 인증 기능에 필요한 모든 것을 만들었다.

 

 

하지만 여기서 테스트할 때 주의해야 할 점은 유니티 에디터 상에서 테스트하는 경우에는 모든 통신의 결과가 성공했다고 가정했다고 진행되기 때문에 제대로된 성공이나 실패 여부를 알고자 한다면 안드로이드로 빌드하여 모바일 상에서 테스트하는 것이 좋다. 또한 유니티 에디터 상에서 테스트된 것은 파이어베이스에 등록되지 않기 때문에 여기서 회원가입에 성공했다고 하더라도 Authentication의 사용자 목록에서는 나오지 않을 것이다. 또한 주의할 점은 만약 제대로된 이메일 주소가 아니거나 비밀번호의 길이가 너무 짧다면 회원가입에 실패할 수도 있다.

 

모바일 상에서 테스트하여 성공적으로 회원가입이 된다면 Authentication의 사용자 목록에 다음과 같이 출력될 것이다.

 

 

로그인에 성공한 유저를 로그아웃 시키고자 한다면 다음의 코드를 활용하면 된다.

 

auth.SignOut();

 

 

 

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

Unity3D 프로젝트와 Firebase 연결하기

 

개요

구글에서 Firebase라는 새로운 서비스가 나왔다. 이 서비스는 구글이 가지고 있는 인프라를 이용해서 별도의 서버실이나 장비 없이도 네트워크를 구축할 수 있도록 도와줄 뿐만 아니라 구글이 제공하는 기능들과 서비스를 이용해서 빠르고 쉽게 개발할 수 있도록 도와준다.

 

 

대표적으로 지원하는 기능은 회원가입, 로그인등을 처리할 수 있는 인증 기능과 NoSQL 기반의 실시간 데이터베이스 등이 있다. 이 구글의 Firebase를 이용해서 간단한 게임 네트워크를 구현할 수 있다.

 

 

연결하기

 

 

https://console.firebase.google.com/?hl=ko

위 주소로 들어가면 Firebase에 프로젝트를 추가할 수 있게 된다.

 

1. 프로젝트 추가를 선택한다.

 

2. 프로젝트 이름을 입력하고 국가를 선택하고 프로젝트 만들기를 누른다.

 

3. 타겟으로 하는 플랫폼을 기반으로 Firebase를 추가해야 한다. 여기서는 Android를 대상으로 Firebase를 추가할 것이다. 위 화면에서 Android 앱에 Firebase 추가를 선택한다.

 

3. Android 패키지 이름을 입력하고 앱 등록을 누른다. 이 이름은 나중에 유니티에도 입력해주어야 한다.

 

4. google-services.json 파일을 다운로드받는다.

 

여기까지 하면 우선 Firebase에서 설정할 작업은 끝났다. 이후의 작업은 유니티에서 해야하는 작업이다. 구글은 유니티에서 사용할 수 있는 파이어베이스 유니티 SDK를 제공하고 있다. 그것은 다음 링크에서 다운로드 받을 수 있다.

 

https://firebase.google.com/docs/unity/setup

 

파이어베이스 유니티 SDK를 다운로드 받았다면 새 유니티 프로젝트를 생성해야한다. 프로젝트가 생성된 이후에는 아까전에 다운로드 받은 google-services.json 파일을 프로젝트에 포함시켜 준다.

 

 

그리고 Edit > Project Settings > Player 에 들어가서 Package Name에 아까 전에 파이어베이스 프로젝트를 생성하면서 입력했던 Android 패키지 이름을 넣어준다.(이 예제에서는 com.firebase.test 이다.)

 

 

그리고 난 이후에 아까전에 받은 파이어베이스 유니티 apk의 압축을 풀어서 그 중에 필요로 하는 기능을 유니티에서 임포트해야 한다.

 

 

이상의 과정이 모두 끝난다면 파이어베이스와 유니티를 연결하는 과정은 모두 끝이 난다. 이후의 섹션에서는 파이어베이스의 각 기능을 활용하는 법에 대해서 알아볼 것이다.

 

추가적으로 이야기해야할 점은, 이번 예시에서 파이어베이스 프로젝트에 등록된 앱은 안드로이드 앱이기 때문에, 유니티로 만든 게임이 파이어베이스 서버에 접속하기 위해서는, 게임을 안드로이드로 빌드해서 모바일에 넣어주어야 한다는 것이다.

 

 

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

유니티에서 프라우드넷으로 네트워크를 구축할 때 위치동기화를 위한 추측항법 사용법

 

 

이 문서를 보기전에 필요한 지식 :

1. 프라우드넷 서버와 클라이언트 구축법.

2. 프라우드넷의 네트워크 전송 방식인 ReliableSend와 UnreliableSend의 차이점

3. 프라우드넷의 RMI, Proxy와 Stub에 대한 지식.

4. 프라우드넷을 통한 게임 네트워크에서 캐릭터 위치 동기화 하는 방법.

5. 유니티 프로젝트에서 프라우드넷을 사용하는 방법.

 

 

1. 캐릭터의 위치 동기화란

캐릭터가 움직일 수 있는 네트워크 게임에서 캐릭터의 위치란 아주 중요한 것이다. 상대방 캐릭터의 실제 위치가 내가 인식한 위치가 다르다면 문제가 될 것이다. 다음의 그림을 보자 : 

 

만약 상대방 캐릭터의 위치 동기화에 실패했다고 가정해보자. 파란색 원이 내 캐릭터이고 분홍색 원은 상대 캐릭터의 실제 위치이며 빨간 원은 위치동기화에 실패해서 상대 캐릭터가 잘못 이동한 위치라고 했을 때, 내가 보이는 대로 빨간색 적을 공격한다면 데미지가 적에게 들어가야할까? 내 입장에서 보이는대로 빨간색 상대를 공격해서 데미지가 들어간다면 나는 납득할 수 있을지 모르겠지만 상대방의 입장에서는 납득하기 어려울 것이다. 상대방이 보기에는 내가 다른 방향을 보고 공격하는데 자신한테 데미지가 들어오는 것으로 보일 것이기 때문이다.

 

이렇듯이 캐릭터의 위치 동기화는 중요하다. 여기에 자주 사용되는 방법은 자신의 캐릭터의 위치가 변경될 때마다 상대방의 클라이언트에 그 변경된 위치를 알려주는 것이다.

 

캐릭터의 위치를 다른 클라이언트에게 전송하는 Proxy

    public void SyncUnitPos(string unitName, UnityEngine.Vector3 pos, Quaternion rot)
    {
        RmiContext context = RmiContext.UnreliableSend;

        client.c2cMessageSender.SyncUnitPos(otherClientHostID, context, unitName, pos, rot);
    }

 

다른 클라이언트로부터 받은 캐릭터의 위치를 자신의 클라이언트에서 찾아서 적용하는 Stub

client.c2cMessageReceiver.SyncUnitMove = (HostID remote, RmiContext rmiContext, string unitName, UnityEngine.Vector3 pos, Quaternion rot) =>
{

Character moveCharacter = AllSpawnUnitDictionary[unitName];

moveCharacter.transform.position = pos;

moveCharacter.transfrom.rotation = rot;

};

 

위의 프록시와 스텁으로 단순하게 캐릭터의 위치를 보내고 받아서 적용하는 것이다. 이 방법은 단순하지만 중요한 단점이 있다. 그것은 바로 여러가지 상황에 따라 캐릭터의 위치를 전송받는 측에서의 캐릭터의 움직임이 끊어져 보일 수 있다는 것이다. 특히 캐릭터의 위치 동기화처럼 네트워크 전송량이 많은 것을 처리할 때는 호스트 간에 메시지를 주고받는 시간이 짧은 UnreliableSend를 사용하기 때문에 메시지의 도착의 확실성이 보장되지 않기 때문에 중간에 잃어버리는 메시지가 많다면 캐릭터의 움직임이 끊어져서 버벅거리면서 이동하는 것처럼 보이거나 텔레포트하는 것처럼 보일 확률이 높아진다.

 

 

2. 추측항법이란

이것을 해결하기 위한 방법이 바로 추측항법이다. 추측항법의 사전적 의미는 다음과 같다 :

 

가장 최근에 구한 정확한 선위를 기초로 선박의 침로와 항정에 의하여 현재의 선위를 추측 및 추정하거나 또는 출발지와 목적지의 경 · 위도를 알고 앞으로 취해야 할 침로 및 항정을 구하는 항법을 추측 항법이라고 한다. 선박이 항행 중에 가장 필요로 하는 것이 바로 선박의 현재 위치이다. 선박의 실측 위치를 얻을 수 없을 때에는, 가장 최근에 실제로 관측하여 구한 실측 위치를 기준으로 하여 그 후에 조타한 진침로와 선속 또는 기관의 회전수로 구한 항정에 의하여 선위를 결정하는 것을 선위의 추측이라 하고, 이와 같이 하여 결정된 선위를 추측위치라 한다.

 

[네이버 지식백과] 추측항법 [dead reckoning sailing, 推測航法] (선박항해용어사전, 한국해양대학교)

 

간단하게 말하면 가장 최근에 확인한 실제 위치를 기준으로 하여 현재의 속도와 방향을 더하여 현재 위치를 추정해내는 것이다. 실제로는 자신의 위치를 특정하기 어려운 항해에서 사용되는 방법인데 이것을 네트워크 게임의 개발에 응용한 것이다. 개념은 기존의 캐릭터의 위치와 방향을 가져와서 바로 적용하는 것에 더해서 캐릭터의 이동 방향과 속도를 함께 가져와서 다음 캐릭터 위치 동기화 신호가 오기전까지 받은 이동 방향과 속도를 이용해서 추정해낸 위치로 미리 캐릭터를 이동시키는 것이다.

 

우리는 이제 추측항법을 구현해야 하겠지만 다행이도 이러한 기능을 구현하는데 도움을 주는 클래스가 이미 프라우드넷에 구현이 되어있다. Nettention.Proud.PositionFollower 라는 클래스이다.

 

그리고 캐릭터의 위치를 동기화 하는 Proxy와 Stub은 다음과 같이 변경될 것이다.

 

캐릭터의 위치를 다른 클라이언트에게 전송하는 Proxy

    public void SyncUnitPos(string unitName, UnityEngine.Vector3 pos, UnityEngine.Vector3 vel, Quaternion rot)
    {
        RmiContext context = RmiContext.UnreliableSend;

        client.c2cMessageSender.SyncUnitPos(otherClientHostID, context, unitName, pos, vel, rot);
    }

 

다른 클라이언트로부터 받은 캐릭터의 위치를 자신의 클라이언트에서 찾아서 적용하는 Stub

client.c2cMessageReceiver.SyncUnitMove = (HostID remote, RmiContext rmiContext, string unitName, UnityEngine.Vector3 pos,  UnityEngine.Vector3 vel, Quaternion rot) =>
{

Character moveCharacter = AllSpawnUnitDictionary[unitName];
moveCharacter.MoveRemote(pos, vel, rot);

};

 

그냥 pos와 rot을 넣어주기만 하면 되던 이전과는 달리 처리할 것이 많으니 Character 클래스에 MoveRemote라는 함수를 만들었다.

 

Character 클래스에서 처리할 것

public class Character

{

// 이 캐릭터가 네트워크를 통해서 간접적으로 조종되는 캐릭터인가?

bool isRemote;

// 추측 항법을 도와줄 프라우드넷의 클래스이다.

Nettention.Proud.PositionFollower posFollower = new Nettention.Proud.PositionFollower();

 

// 네트워크의 stub을 받아 Follower의 위치를 설정한다

public void MoveRemote(Vector3 pos, Vector3 vel, Quaternion rot)

{

var npos = new Nettention.Proud.Vector3();
npos.x = pos.x;
npos.y = pos.y;
npos.z = pos.z;
      
var nvel = new Nettention.Proud.Vector3();
nvel.x = velocity.x;
nvel.y = velocity.y;
nvel.z = velocity.z;

 

posFollower.SetTarget(npos, nvel);

transform.rotation = rot;

}

 

// Follower에 따라서 캐릭터를 이동시킨다

public void FollowRemoteMove()

{

posfollower.FrameMove(Time.deltaTime);

var pos = new Nettention.Proud.Vector3();

var vel = new Nettention.Proud.Vector3();

posfollower.GetFollower(ref pos, ref vel);
unit.transform.position = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
unit.transform.rotation = Quaternion.Lerp(unit.transform.rotation, destRot, Time.deltaTime * 100);

}

 

void Update()

{

if (isRemote) FollowRemoteMove();

}

}

 

이 방법을 사용할 때는 자신의 캐릭터와 상대방의 캐릭터, 즉 직접 조종하는 캐릭터와 네트워크를 통해서 조종되는 캐릭터를 명확하게 구분해야 한다.

 

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

유니티 에디터의 글씨가 빨간색으로 나오는 버그

 

유니티 엔진을 사용하다보면 다음과 같이 UI의 글자들이 빨간색으로 나오는 버그가 발생한다. 빨간색이 주는 강렬함 때문에 이 현상을 목격한 개발자는 이게 아주 심각한 버그가 아닌가 하고 당황에 빠지게 되는데 이 상황에서는 절대로 당황해서는 안된다.

 

뭔가 심각한 버그가 아닌가 하고 작업을 롤백한다던지, 무언가 다른걸 시도하는 작업자들이 있는데 그렇게 할 경우, 진행했던 며칠간의 작업을 날린다던지 하는 문제가 발생할 수 있다. 하지만 이 버그는 결코 심각한 버그는 아니다. 단지 간단한 GUI 버그일 뿐이다.

 

그냥 무시하고 작업을 진행하다 보면 어느 샌가 정상으로 돌아온 유니티 엔진을 볼 수 있다. 저 빨간색 글씨들이 너무 거슬린다면 침착하게 현재 진행중인 작업을 저장하고 난 뒤에 유니티를 재시작하는 방법도 있다.

 

다음과 같은 상황을 맞이하게 된다면 절대 당황하지 말고 작업을 저장하라.

 

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

+ Recent posts