유니티(Unity) Netcode for GameObject 활용편 #1 (전반적인 Setting부터 시작하여 Transform동기화와 Data동기화까지)

설명에 앞서

 

Netcode for GameObjects이란? Import방법

❓Netcode for GameObjects이란? Netcode for GameObjects은 네트워킹 로직을 추상화 할 수 있도록 Unity를 위해 만들어진 High-level 네트워킹 라이브러이다 한 번에 멀티플레이어들에게 네트워킹 세션을 가로질

wlsdn629.tistory.com

 

 

위 포스팅을 참고해서 [NetCode for GameObjects] Package를 Import 하고 오셔야 합니다.


Transform동기화 방법부터 Data동기화 방법까지

NetworkManager

빈 오브젝트를 하나 생성한 후 NetworkManager라고 이름을 바꿔줍니다.

그다음, NetworkManager오브젝트에 NetworkManager 컴포넌트를 부착해 줍니다.

 

com.unity.multiplayer.tools

Package Manager 폴더로 들어가서 [Multiplayer Tools] Package를 임포트 해줍니다.

 

https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop.git?path=/Packages/com.unity.multiplayer.samples.coop#main

 

마지막으로 NetworkManager의 [Select transport]을 눌러준 다음 Unity Transport를 선택해 줍니다.


Unity Transport란?

 

유니티(Unity) Untiy Transport Package(UTP)에 대해서 (#Relay 2편)

Relay SDK는 Unity Transport Package (UTP)에서 잘 작동됩니다 About Unity Transport | Unity Multiplayer Networking Unity Transport provides the com.unity.transport package, used to add multiplayer and network features to your project. docs-multiplay

wlsdn629.tistory.com

위 포스팅을 참고해 주시면 되겠습니다.


Transform 동기화

Transform을 동기화 연습을 위해 캡슐 오브젝트를 하나 생성해 준 후 Player라고 바꿔줍니다.

Player에 NetworkObject 스크립트를 부착해 준 후 프리팹으로 만들어줍니다.

 

방금 만든 Player 프리팹을 NetworkManager에 Player Prefab에 넣어줍니다.

Player Prefab에 들어간 프리팹은 각 플레이어가 서버에 연결될 때 자동으로 생성됩니다.

 

Network Prefabs에 방금 만든 Player 프리팹을 넣어줍니다.

용어  설명
Player
Prefab
Player Object를 인스턴스화하고 연결하여 인증된 클라이언트에게 할당하는 역할을 합니다.
주로 게임 메인 캐릭터를 나타냅니다.
Network
Prefabs
각 지정된 네트워크 프리팹을 오버라이드하고 싱글 네트워크 프리팹으로 만들 수 있게 해주는 역할을 합니다.
필요에 따라 Instantiate할 때 필요한 프리팹을 제공하며, 싱글 프리팹을 네트워킹 공유할 수도 있습니다.

UI 세팅하기

위와 같이 버튼을 배치해 줍니다

NetworkManagerUI Panel을 만든 후 Panel에 3개의 버튼(Server, Host, Client)을 만들어줍니다. NetworkManagerUI스크립트를 만든 후 NetworkManagerUI Panel 게임오브젝트에 붙여줍니다.

using UnityEngine;
using UnityEngine.UI;
using Unity.Netcode;

public class NetworkManagerUI : NetworkBehaviour
{
    [SerializeField] Button serverBtn;
    [SerializeField] Button hostBtn;
    [SerializeField] Button clientBtn;

    void Awake()
    {
        serverBtn.onClick.AddListener(() => NetworkManager.Singleton.StartServer());
        hostBtn.onClick.AddListener(() => NetworkManager.Singleton.StartHost());
        clientBtn.onClick.AddListener(() => NetworkManager.Singleton.StartClient());
    }
}

 


에디터를 실행시킨 다음, 3개의 버튼 중 Host 버튼을 클릭하면 Player가 Spawn 되는 것을 볼 수 있습니다.


플레이어 이동시키기

새로 만들어야함

PlayerNetwork 스크립트를 하나 만든 후 위와 같이 코드를 작성해 준 다음, Player에게 붙여줍니다.

 

코드에서 핵심적으로 볼 부분은 다음과 같습니다.

using Unity.Netcode와 NetworkBehaviour을 상속받는다는 점과 IsOwner(소유권이 본인이 아니면)가 아니면 return 한다는 점입니다.

 


마지막으로 Player 프리팹에 Client Network Transform컴포넌트를 붙여줍니다.

Network Transform을 쓰지 않고 Client Network Transform을 붙여주는 이유는 아래와 같습니다.

 

Network Transform의 경우 서버 권위적인 로직이어서 클라이언트가 서버에게 변경된 Transform을 보내고 Server가 허락해 준 다음 변경된 값들을 클라이언트들에게 뿌리는 형식입니다.

  설명
서버
권위적인 로직
서버가 네트워크 오브젝트의 Transform 변경을 관리하므로, Client는 변경 요청을 서버에게 보내고 서버가 승인해야 합니다. 이로써 서버는 전체적인 게임 논리를 조절하고 보안을 강화할 수 있습니다.

 

Client Network Transform의 경우를 사용하는 이유는 Client가 Transform 값을 직접 변경할 수 있게 하므로 서버 권한을 필요로 하지 않습니다. 이를 통해 Client는 서버에 대한 의존성 없이 자체적으로 오브젝트의 Transform을 조작할 수 있습니다.

 

서버로 패킷을 넘길 때 최소화된 정보를 넘겨줘야 하므로 불필요한 정보는 UnCheck 해줍니다.


정보(Data) 동기화 

정보(Data)도 동기화 잘되는지 Test 해보겠습니다. 코드를 위와 같이 작성해 주시면 됩니다.

 

이 스크립트로 Test를 해보면, Server 쪽에서 T키를 눌렀을 경우 문제없이 잘 작동하지만 클라이언트 쪽에서 T키를 눌렀을 경우 에러(Error)가 발생합니다.

 

그 이유는 NetCode는 앞서 설명드렸다시피 서버 권위적이므로 클라이언트 쪽에서 데이터를 마음대로 수정할 수 없기 때문입니다.

 

이럴 경우 아래와 같이 해결해 줄 수 있습니다.


 

데이터 수정을 클라이언트에(소유자=Owner)게도 할 수 있게 권한을 부여해 주면 됩니다.

 

위 코드와 같이 데이터 수정을 Write를 Owner에서 Everyone으로 해주면 됩니다.


에디터를 실행시킨 후 T키를 눌러 확인해 보시면 잘 작동하는 것을 볼 수 있습니다.