| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 |
- ECS
- 공정한경쟁
- 넷코드
- 2023 경기게임잼
- 유니티
- 객체지향의사실과오해 #객체지향
- 2023 버닝비버
- 2023 비버잼
- 쫄?
- Wings2022
- Unity
- 역행자
- 모토가있는하루
- 페스트 #알베르카뮈
- Wings2022굿즈
- Netcode
- InputSystem
- custommessaging
- 보통일베들의시대
- 메이플스토리월드
- #스타를#하다보니#최적화맛들림#42미네랄#앞마당파일런
- 프로이트 #쾌락원칙을넘어서
- 게임개발
- 강화학습
- Catverse
- 바닥부터배우는강화학습
- 브레이킹 루틴
- MapleStoryWorlds
- necode
- 인디게임개발
- Today
- Total
이문회우
[Unity Netcode] 커스텀 메시징 2. Just chatting 본문
[Unity Netcode] 커스텀 메시징 1. 개념 잡기
[Unity Netcode] 커스텀 메시징(CustomMessagingManager) - 1
멀티 게임을 만들어보자. ※ 개발 환경은 Unity 6이다.Netcode우선 Unity Netcode 패키지를 설치한다.Window > Package Manager > Packages: Unity Registry > Netcode for GameObject Unity Netcode는 Unity에서 멀티 플레이 개발
koesob.tistory.com
이어서 글을 써보자.
1편의 글은 개념 구조 설명을 위한 코딩이었을 뿐 실제로 동작하지는 않는다.
네트워크 다루는 프로그래밍인데 정작 네트워크 연결 과정은 포함 안 시켰거든.
바로 시작해보자.
접속
우선, Managers 코드를 변경해준다.
using Unity.Netcode;
using UnityEngine;
public class Managers : MonoBehaviour
{
public void StartServer()
{
NetworkManager.Singleton.StartServer();
}
public void StartClient()
{
NetworkManager.Singleton.StartClient();
}
public void StartHost()
{
NetworkManager.Singleton.StartHost();
}
}
더 이상 메시지 등록과 전송에 대한 구현은 필요 없기 때문에 해당 부분을 지웠다.
대신 '접속'과 관련한 함수를 추가했다.
Server : 게임 진행자. 게임이 생성되는 컴퓨터이며 진행 연산을 도맡아 한다. 따라서 게임 내 정보를 모두 갖고 있다.
Client : 게임 참가자. 플레이어로부터 입력을 Server로 전달한다. 그에 따라 Server가 수행한 연산 결과를 받는다.
Host : 게임 진행자이자 참가자이다.
각각의 함수는 '이 컴퓨터를 Server/Client/Host 역할을 하는 컴퓨터로 NetworkManager에 등록하겠다'라는 뜻이다.

이제 Managers를 씬에 만들어주자. 빈 오브젝트를 만든 후, Managers 컴포넌트를 추가해줬다.

그리고 플레이어가 상호작용 할 수 있도록 UI > Button - TextMeshPro로 버튼을 만들어주고, 이름을 Button_StartHost로 바꿔준다.
처음으로 Button - TextMeshPro를 하면, TextMeshPro 패키지를 설치하는 과정이 진행되는데, TextMeshPro는 문자 표시 + 문자 관련해서 특수 효과 처리를 돕는 패키지이다. 최근 유니티는 이 TextMeshPro로 문자 표시 기능을 제공한다. 다만 복잡한 기능 구현은 하지 않을 예정이므로 Essential만 설치해도 문제 없다.
이제부터 빠른 진행을 위해 이미지 달리겠다.





위 과정은 해당 버튼을 눌렀을 때, 어떤 동작을 할지 선택하는 과정이다.
이 버튼은 이제 누르면 Managers.StartHost 동작이 이뤄진다.

위 과정을 두 번 더 반복해서, Start Servr, Start Client 버튼 또한 만들어주자.
버튼에서 Managers.StartServer, Managers.StartClient로 바꿔주는 과정 또한 잊지 말기.
자, 근데 이 다음 어떻게 해야할까.
실행을 시켜서 Start Host 버튼을 누른다한들, 다른 컴퓨터에서 Start Client를 누르지 않으면 아무 의미가 없다.
따라서, 공식 문서에서는 빌드해서 별도의 게임 파일로 만든 후 테스트를 진행하라고 한다.
하지만 기능 하나 만들 때마다 빌드를 한다면 시간 낭비도 그런 낭비가 없다.
이 점 또한 알고 있기에 하나의 컴퓨터에서 여러 플레이어를 띄울 수 있는 패키지가 존재한다.
Multiplayer Play Mode
About Multiplayer Play Mode | Unity Multiplayer
About Multiplayer Play Mode | Unity Multiplayer
Overview of Multiplayer Play Mode
docs-multiplayer.unity3d.com
간단하다. 최대 3명까지 가상의 플레이어를 띄워준다.

설치 방법은 위와 같다. 6 버전 이전에는 깃허브 url을 직접 등록해야했는데 세상, 많이 편해졌다~

설치를 하고나서 Windows > Multiplayer Play Mode를 눌러주면,

위와 같이 Virtual Player를 만들 수 있는 창이 뜬다. Player2에 체크 표시를 해서 가상의 플레이어 2를 만들고 테스트를 진행해보자.

짜잔, 두 명의 플레이어 화면이 들어온다.
※ 처음 게임을 실행시키면, '현재 씬이 등록되어 있지 않습니다. 등록하시겠습니까?'라는 창이 뜨는데 확인하고 진행하면 된다!
이제 한 쪽에서 Start Host를, 다른 쪽에서 Start Client를 누르면 정말로 연결된다.
단, 이 연결은 한 컴퓨터니까 가능한 연결이다.
실제로는 상대방 컴퓨터의 네트워크 정보가 필요하고 연결하는 과정이 필요하다.
당연히 이 복잡함을 감춰줄 Relay라는 Unity의 서비스가 존재한다. 흔히 '연결 코드'라고 불리는 그것이다.
지금은 상호 간 동작만 보면 되기 때문에 다루지 않지만, 연결이 필요한 순간이 오면 다룰 예정이다.
다만, 현재로썬 뭐가 달라졌는지 알 수가 없다. 그도 그럴 것이 Managers.StartHost/Server/Client는 딱 연결 기능만 할 뿐, 로그를 찍거나, UI를 변화시키는 등의 기능은 넣지 않았기 때문이다.
그래도 각 플레이어의 NetworkManager를 확인해보면 변화가 있음을 알 수 있다.


두 번째 플레이어의 창 레이아웃 변경시키는 것은 왼쪽 위 Layout에서 Hierachy와 Inspector를 체크 표시해주면 된다.
각 씬의 Unity Transport 컴포넌트에 숫자를 잘 보면, Address가 127.0.0.1을 가리키는 것을 알 수 있다. 이 값은 내 컴퓨터의 IP 주소를 의미하는 것으로, 앞서 말했듯 현재 연결은 '내 컴퓨터 안' 이니까 가능한 연결이다.
자, 최소한의 로그는 남겨보자.
using Unity.Netcode;
using UnityEngine;
public class Managers : MonoBehaviour
{
public void StartHost()
{
NetworkManager.Singleton.StartHost();
Debug.Log("이제부터 이 컴퓨터는 Host입니다.");
}
public void StartServer()
{
//NetworkManager.Singleton.StartServer();
// 일단 서버는 작동하지 않는걸로.
Debug.Log("Server는 동작하지 않습니다. Start Host 버튼을 눌러주세요.");
}
public void StartClient()
{
NetworkManager.Singleton.StartClient();
Debug.Log("이제부터 이 컴퓨터는 Client입니다.");
}
}
Start Server 버튼은 헷갈릴 수 있기 때문에 로그만 남길 뿐 네트워크 연결은 수행하지 않도록 수정했다.
Host와 Client로만 갖고 놀자.

본격적인 Messaging을 해보자
Messaging
해볼 것은 아주아주 간단한 채팅이다.
using System.Collections.Generic;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
public class Managers : MonoBehaviour
{
public void StartHost()
{
NetworkManager.Singleton.StartHost();
Debug.Log("이제부터 이 컴퓨터는 Host입니다.");
// 메시지 처리 등록!
Register();
}
public void StartServer()
{
//NetworkManager.Singleton.StartServer();
// 일단 서버는 작동하지 않는걸로.
Debug.Log("Server는 동작하지 않습니다. Start Host 버튼을 눌러주세요.");
}
public void StartClient()
{
NetworkManager.Singleton.StartClient();
Debug.Log("이제부터 이 컴퓨터는 Client입니다.");
// 메시지 처리 등록!
Register();
}
private void Register()
{
// JustChat 메시지 이벤트에 OnReceived를 등록한다.
NetworkManager.Singleton.CustomMessagingManager.RegisterNamedMessageHandler("JustChat", OnReceived);
}
private void OnReceived(ulong clientID, FastBufferReader reader)
{
// 메시지를 받으면 string reply로 읽고, reply를 로그로 남긴다.
reader.ReadValueSafe(out string reply);
Debug.Log(reply);
}
}
일단, Host 컴퓨터도, Client 컴퓨터도 메시지를 받으면 로그를 남길 것이다.
그럼 이제 메시지를 보내보자.
using System.Collections.Generic;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
public class Managers : MonoBehaviour
{
// 메시지를 입력할 Text 공간을 만들었다.
// 곧 UI로 만들 예정
public TMP_Text message;
// ...
public void Send()
{
// 아직 받는 사람 정보가 없다.
ulong targetClientID = 0;
FastBufferWriter writer = new FastBufferWriter(size: 128, allocator: Allocator.Temp);
// message 내용을 싣는다.
writer.WriteValueSafe(message.text);
NetworkDelivery networkDelivery = NetworkDelivery.ReliableSequenced;
if (NetworkManager.Singleton.IsHost)
{
// ConnectedClientsIds에 접근할 수 있는 것은 Host니까 가능함
// Client에서는 안된다.
List<ulong> clientIDs = new List<ulong>(NetworkManager.Singleton.ConnectedClientsIds);
clientIDs.Remove(NetworkManager.Singleton.LocalClientId);
// 메시지를 보낼 때, List 값을 주면 List에 있는 모든 Client에게 메시를 보낸다.
NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("JustChat", clientIDs, writer, networkDelivery);
}
else if(NetworkManager.Singleton.IsClient)
{
// Client에서는 ServerClientId는 알 수 있다.
targetClientID = NetworkManager.ServerClientId;
// Server에게 메시지 보내기
NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("JustChat", targetClientID, writer, networkDelivery);
}
else
{
return;
}
}
}
코드에서 읽을 수 있듯이, NetworkManager를 통해서 현재 컴퓨터의 ClientID를 얻을 수 있다.
그리고, Host는 자신에게 연결된 다른 ClientID까지도 알 수 있다.
그러고나서 FastBufferWriter에 message를 싣고 보내고 있다.

그러고나서 씬을 위와 같이 변경했다.
1. UI > Input Field - TextMeshPro 로 플레이어의 입력을 받은 UI를 만들었다.
크기와 위치 적절히 배치해주고, 폰트 사이즈도 적절히 만들어주자.
2. UI > Button - TextMeshPro 로, 입력한 메시지를 보낼 때 쓸 버튼 또한 만들었다.
마찬가지로 크기와 위치, 폰트 사이즈를 적절히 맞춰주자.

특히, 2에서 만든 Button_Send에 방금 추가한 Managers.Send 기능을 연결하는 것도 잊지 않기

1. Start Host 하기
2. 다른 플레이어에서 Start Client 하기
3. Host 컴퓨터에서 메시지 입력. ※ TextMeshPro의 기본 폰트는 한글 지원이 안된다. 영어를 입력하자.
4. Send!
오른쪽 Client 컴퓨터에 잘 뜨는 것을 볼 수 있다.

Client 컴퓨터에서도 원활히 동작하며 뛰어난 영어 실력을 뽐내고 있다.
자, Custom Messaging을 간단히 다뤄봤다.
지금은 string 값만 간단히 주고 받았지만 이제 string 값이 아니라 다양한 게임 데이터를 주고 받으면 게임이 되는 것이다.
더 구체적인 프로그래밍은 다음 시간에 계속.
'개발 > [Unity]만 골라보기' 카테고리의 다른 글
| [Unity Netcode] 커스텀 메시징 1. 개념 잡기 (1) | 2024.12.25 |
|---|---|
| [Unity UI Toolkit] 공식 문서 읽기 (0) | 2023.05.15 |