네트워크 애니메이터(Network Animator)

 

네트워크 게임에서는 게임이나 유닛, 캐릭터 등의 상태를 동기화하는 것도 중요하지만 눈에 보이는 캐릭터들의 움직임, 즉 애니메이션 역시 동기화가 필요하다. 아무리 다른 동기화가 잘 되고 있다고 하더라도, 애니메이션 동기화가 진행되지 않아서 가만히 서있는 자세로 이동하거나 공격한다면 문제가 많을 것이다.

 

유니티 네트워크 시스템에서는 이러한 애니메이션 동기화를 위한 기본적인 기능을 제공하는데 그것이 바로 네트워크 애니메이터(Network Animator)다.

 

이번 섹션을 진행하기 위해서는 기본적인 유니티의 애니메이션 시스템과 애니메이터 컨트롤러에 대한 지식이 필요하다. 기반 지식이 부족하다면 유니티의 애니메이션 문서를 참조하여 공부를 해두는 것이 좋다.

 

그럼 이제부터 네트워크 애니메이터를 사용하는 방법을 알아보도록 하자.

 

 

네트워크 애니메이터 컴포넌트의 기본적인 요구사항

 

 

 

네트워크 애니메이터를 사용하기 위해서는 네트워크 애니메이터 컴포넌트가 있는 오브젝트와 같은 오브젝트에 에니메이터 컨트롤러와 네트워크 아이덴티티 컴포넌트가 있어야 한다.

 

 

네트워크 애니메이터의 작동 방식

 

 

네트워크 애니메이터의 작동 방식은 기본 애니메이터 컨트롤러의 파라메터가 변경되면 그 변경된 파라메터의 값을 네트워크 애니메이터를 통해서 클라이언트의 해당 네트워크 애니메이터로 전송하고 받은 측의 네트워크 애니메이터가 자신이 소유한 애니메이터 컨트롤러에 변경된 파라메터와 값을 알려서 애니메이션을 동작하게 한다.

 

 

 

 

 

네트워크 애니메이터를 사용하기 위한 준비

 

앞에서 네트워크 애니메이터의 기본적인 요구 사항과 작동 방식을 알아보았으니 이제 네트워크 애니메이터를 추가하고 사용하는 방법에 대해서 알아보도록 하자.

 

 

 

애니메이션 섹션의 단골인 박스맨이 이번 네트워크 애니메이터 섹션에서도 도움을 줄 것이다.

 

 

 

위의 이미지에 맞춰서 애니메이션 스테이트를 구성해보자. 박스맨 캐릭터는 대기(Idle) - 이동(Walk) - 공격(Attack), 세 가지 상태를 가지며, IsMove 파라메터의 상태에 따라서 대기와 이동 상태를 오가며, Attack 트리거를 받으면 공격 애니메이션을 재생하고 대기 상태로 돌아가는 아주 간단한 형태다.

 

 

 

위와 같이 게임 오브젝트와 컴포넌트를 세팅해주면 준비는 끝이다.

 

 

 

 

네트워크 애니메이터 추가하기

 

 

네트워크 애니메이터를 추가하는 방법은 간단하다. 애니메이션을 동기화하고자 하는 오브젝트에(애니메이터 컨트롤러 컴포넌트를 가지고 있어야 한다) 네트워크 애니메이터를 Add Component 해주면 된다. 그러면 네트워크 애니메이터와 함께 네트워크 통신에 필요한 Network Identity 컴포넌트가 자동으로 함께 추가된다.

 

 

 

네트워크 애니메이터를 추가한 후에는 네트워크 애니메이터 컴포넌트의 애니메이터 프로퍼티에 동기화되어야할 애니메이터를 추가해주면 된다.

 

 

그렇게하면 네트워크 애니메이터 컴포넌트에 동기화될 애니메이터의 파라메터들이 표시된다. 이 다음에는 네트워크 애니메이터를 컨트롤할 스크립트를 작성해야 한다.

 

using UnityEngine;
using UnityEngine.Networking;

public class PlayerCharacter : MonoBehaviour
{
    private NetworkAnimator netAnimator;

    void Start ()
    {
        netAnimator = GetComponent<NetworkAnimator>();
    }
   
    void Update ()
    {
        if (Input.GetKeyDown(KeyCode.W))
        {
            netAnimator.animator.SetBool("IsMove", true);
        }
        else if (Input.GetKeyUp(KeyCode.W))
        {
            netAnimator.animator.SetBool("IsMove", false);
        }

        if (Input.GetMouseButtonDown(0))
        {

            netAnimator.animator.SetTrigger("Attack");
            netAnimator.SetTrigger("Attack");
        }
    }
}

 

위와 같이 스크립트를 작성한 이후에 빌드하고 실행해서 한 쪽에서 서버를 열고 다른 쪽에서 클라이언트로 접속한 뒤 서버 측에서 W를 누르거나 마우스를 클릭했을때 애니메이션이 동기화됨을 확인할 수 있다.

 

 

위의 예시 코드에서 몇 가지 의문점이 있을 수 있는데, SetBool을 호출할 때는 networkAnimator.animator를 통해서 호출하고 SetTrigger를 호출할 때는 networkAnimator.SetTrigger()로 바로 호출하는가와 트리거를 사용하는 부분에서 왜 networkAnimator.animator.SetTrigger()와 networkAnimator.SetTrigger()를 중복해서 사용했는지가 그것이다.

 

첫 번째 의문점의 경우에는 Trigger는 NetworkAnimtor 클래스에서 호출할 수 있는 SetTrigger() 함수가 있지만, 다른 애니메이터의 파라메터(Int, Float, Bool)는 NetworkAnimator 클래스에서 바로 호출해서 사용하는 메서드가 따로 없고, NetworkAnimator의 멤버 변수인 animator를 통해서 SetBool(), SetInt(), SetFloat() 함수를 호출하도록 만들어져 있기 때문이다.

 

두 번째 문제는 트리거를 사용하는 부분에서 왜 networkAnimator.animator.SetTrigger()와 networkAnimator.SetTrigger()를 중복해서 사용했는지 인데, 이것은 networkAnimator.animator.SetTrigger() 함수를 통해서 동작하는 애니메이션은 서버에서만 재생되고, networkAnimator.SetTrigger() 함수를 통해서 동작하는 애니메이션은 클라이언트에서만 재생되기 때문이다. 즉, 서버에서도 애니메이션을 재생하고 클라이언트에서도 애니메이션을 재생하기를 원한다면 위의 예시 코드와 같이 작성되어야 한다. 특히 서버 측에서 애니메이션 이벤트를 통해서 애니메이션이 진행되는 도중에 특정한 동작이 발생되도록 로직이 짜여있다면 서버에서도 애니메이션이 동작되어야 하기 때문에 반드시 위의 코드처럼 작성되어야만 한다. 하지만 이후에도 설명하겠지만, 애니메이션을 재생하는 처리는 상당히 무거운 작업에 속하기 때문에, 클라이언트가 서버의 역할을 함께하는 P2P 방식이 아닌 순수한 서버라면 애니메이션 재생 도중 호출되는 애니메이션 이벤트는 반드시 배제해야 한다. 그리고 서버에서는 애니메이션이 완전히 동작하지 않도록 하는 것이 좋다.

 

 

 

 

추가로 : 네트워크 애니메이터에 대한 중요한 사실

 

유니티에서 기본적으로 제공하는 네트워크 애니메이터가 있기 때문에 우선은 소개하고 사용법에 대해서 알려주지만, 사실 기본 네트워크 애니메이터를 사용하는 것은 추천하지 않는다. 오히려 직접 커스텀 네트워크 애니메이터를 따로 구현해서 사용하도록 권장하고 싶다. 지금은 주요 작업을 2017.3.03f 버전의 유니티로 하고 있기 때문에 이후의 버전에서는 더 좋게 바뀌었는지 모르겠지만, 이 버전과 이전 버전에서는 기본 네트워크 애니메이터에 상당한 문제가 있기 때문이다.

 

첫 번째 문제는, 기본 네트워크 애니메이터가 소모하는 데이터량이 너무 많다. 커스텀 애니메이터를 잘 구현한다면 기본 네트워크 애니메이터를 사용할 때보다 훨씬 데이터 소모량을 많이 줄일 수 있다.

 

두 번째 문제는, 꽤나 심각한 문제인데, 기본 네트워크 애니메이터가 굉장히 많은 가비지(Garbage)를 발생시켜서 GC로 인한 프레임드랍이 심각하다고 여겨질 만큼 발생한다는 것이다. 이것에 대한 이슈는 구글링해보면 해외 개발자들도 상당히 심각하게 느끼도 있다는 것을 알 수 있다. 실제 개발에서 네트워크 애니메이터로 애니메이션을 동기화 했다가 이 문제 때문에 네트워크 애니메이터를 모두 제거하고 커스텀 네트워크 애니메이터를 구현해서 사용해야 했었다.

 

 

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

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

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 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. modernator 2018.09.30 01:21

    잘보고 갑니다. UNet의 NetworkAnimator는 잘모르겠지만, 예전에 Photon Unity Networking의 NetworkAnimator 코드를 분석한 적이 있었는데요, 동기화를 위해서 어마어마한 작업들을 하더군요. 간단한 데모 구현이나 가벼운 게임이 아니라면 말씀하신대로 직접 스크립트로 필요한 경우에만 동기화하는게 제일 좋은것 같습니다.

    • wergia 2018.10.01 11:08 신고

      유넷이 기본 제공하는 네트워크 애니메이터는 사실상 프로토타이핑용인 것 같습니다.

  2. mimus 2018.11.15 23:07

    안녕하세요 unet 관련 설명을 잘봤습니다 ㅎㅎ..
    다름이 아니라 이번에 혼자서 unet으로 VR 게임을 제작 하는데 문제가 생겨서 질문을 좀드립니다ㅠㅠ..
    멀티플레이 방식을 internt 방식을 사용해서 제작하니 방을 만든 사용자의 움직임은 방에 접속한 사람에게 보이는데
    방에 접속한 사람의 움직임은 방을 만든 사용자에게 보이지가 않습니다..
    동기화 방식은 networkTransform 을 사용했습니다..

    혼자서 아무리 생각을 해봐도 이유를 모르겠습니다 ㅠㅠ

    아그리고 추가 로 질문을 하면 혹시 internet 방식으로 멀티플레이를 하게되면 방을 만든 사람 만 local player로 인식 되는건가요?..
    답변 기다리겠습니다 ㅠ

    • wergia 2018.11.16 11:13 신고

      움직임이 보이지 않는다는 것은 애니메이션이 보이지 않는다는 의미인가요? 아니면 위치 동기화가 되지 않는다는 의미인가요?

      1. 만약 애니메이션이 보이지 않는다는 뜻이라면 방을 만들때 StartServer로 하셨나요?
      방을 만드는 사람이 플레이어로 참여하려면 StartServer로 방을 만들기보다 StartHost로 방을 만들어야 합니다. Server의 경우 기본적으로 서버로서의 계산만을 하기 때문에 기본 NetworkAnimator의 경우 애니메이션 재생을 배재하기때문에 애니메이션 동기화가 되지 않을 수 있습니다.

      2. 만약 위치 동기화가 되지 않는다면 authority 문제일 확률이 제일 높습니다. 일반적으로 네트워크 게임에서 동기화하는 권한은 서버 역할을 하는 호스트에게 있어야만 합니다. 그런데 만약 권한이 로컬 플레이어가 가지게 된다면 호스트 역할을 하는 플레이어의 경우 서버역을 겸하기 때문에 방에 접속한 다른 사용자에게 위치 동기화가 되지만, 클라이언트로서 접속한 플레이어의 위치 동기화가 이루어지지 않는 문제라고 생각됩니다.
      플레이어 프리팹 오브젝트의 NetworkIdentity 컴포넌트에서 Local Player Authority를 확인해보세요.

    • mius 2018.11.16 15:12

      감사합니다! 덕분에 해결 했습니다!

  3. myouzing 2019.08.05 23:09

    안녕하세요 unity를 공부하고 있는 학생입니다.
    저는 이제까지 single fps 게임을 개발하였습니다. 그 후에 multi player로 발전시키는 과정에서 문제가 생겨 여쭤보고 싶습니다. ㅠㅠ
    우선, 문제점은 제가 single에서 넣어놓은 적 애니메이션은 player와 관련이 있었습니다.
    player가 존재하면 걷고, 가까워지면 player를 공격하고 하는 등등의 애니메이션을 적용한 것입니다
    그러나, 제가 player에게 networkmanager를 적용시켰을 때 player를 인식하지 못하는 문제점이 있는 것 같습니다.
    이 문제에 대해 혹시 조언을 구할 수 있을까요..?
    답변 주시면 정말 감사하겠습니다 !

    • wergia 2019.08.19 17:53 신고

      상황을 정확히 알 수 없어서 자세한 답변은 어렵지만 대강 짐작가는 부분에 대한 답변을 드립니다.

      https://wergia.tistory.com/176

+ Recent posts