- 잡설
몇년 전 유니티는 네트워킹 솔루션 UNet을 deprecated화 시키면서 이를 유니티에 더 이상 사용하지 않을 것을 권고 했었다.
아무런 대체품 없이 개발 중단 한 것과 같아서... 포톤이나 Mirror같은 솔루션을 이용하거나, 직접 네트워크 코드를 짤 수 밖에 없는 큰 공백 상황에 던저져 버렸었다.
그리고 작년 쯤 유니티에서 제공하는 UNet의 대체제가 나오게 되었는데, 그것이 MLAPI이다.(현재는 Netcode라는 이름으로 바뀐듯)
이름 좀 그만 바꿔... 자료 찾는거 너무 어렵다...😭😢
최근... 올해 6월 말에 버전명에서 pre가 사라지면서 프리뷰버전에서 정식버전이 되었는데, 네트워킹이 되는 프로그램을 아직 제대로 작성해 본 적이 없는 만큼 공부해 보고자 한다.
공식 문서 번역
원본 문서 링크 | https://docs-multiplayer.unity3d.com/netcode/current/tutorials/helloworld |
문서 참조 기준 날자 | 2022. 10. 08 |
번역에 대한 주석(잡설)은 밑줄이 있는 흐린 글 로 표시하도록 하겠습니다. 원래 문서에는 없던 내용이니 혹시나 읽으실 분은 참고!
MLAPI 버전이 정식으로 올라 왔다고는 하지만... 계속해서 버전이 올라가는 만큼, 공식 문서 또한 많이 달라지는 부분이 있을 것 같다.
이 글은 그냥 나 혼자 공부하려고 올려 둔 내용이니... 너무 믿지 말고 공식 문서를 직접 들어가서 보자.(한글 번역이 없고 온통 영어긴 하지만...😥)
제목 : 당신의 네트워킹 Hello World 코드 프로젝트
Hello World(헬로 월드) 프로그램은 Hello World를 결과물로서 출력하는 컴퓨터 프로그램입니다. 보통 코딩하는 법을 배우기 위한 사람들이 가장 처음으로 작성하는 프로그램이기도 합니다. 또한 정상적으로 컴퓨터 언어가 올바르게 설치되었는지, 사용자가 사용하는 방법을 이해 했는지 확인하기 위한 용도로 사용되기도 합니다.
이 Hello World 듀토리얼에서는 여러분이 프로젝트를 생성하고, Netcode for GameObject (Netcode 패키지)를 설치하며, 여러분의 첫 네트워킹이 동작되는 게임을 위한 기본 컴포넌트를 생성하는 방법에 대해 다뤄 보겠습니다.
이 문서는 골든 패스 시리즈의 기반이기도 하니 다른 문서도 참고해 주세요.
✅ Note
여기에 있던 영상은 너무 오래 되었고 주는 도움에 비해 더 많은 오해를 불러 일으킬 수 있어 제거 되었습니다. 모든 Hello world와 골든 패스 시리즈에 존재 하던 영상은 추후에 다시 만들어서 추가될 것입니다.
아직은 만들어진지 몇년 되지 않아 문서가 부족한 부분이 많다보니 이런 문장이 있는듯하다만... 아쉽다.
그렇지만 넷코드 말고 유니티엔진 공식 문서에도 영상이 없는 부분이 많으니까 이해가 필요한 부분일지도.... 흐음... 🤔😥
유니티에서 첫 프로젝트를 만들기
- Unity Hub (유니티 허브)를 여세요.
- New (새 프로젝트) 버튼을 클릭합니다.
- 템플릿 타입을 3D로선택합니다.
- 프로젝트 이름을 Hello world로 명명하세요.
- 여러분이 프로젝트를 저장할 위치를 선택하세요.
Netcode(넷코드) 설치하기
넷코드 설치 가이드를 참고하셔서 넷코드를 설치해 보세요.
기본 컴포넌트를 만들어봅시다.
이 구역에서는 멀티플레이어 게임의 기본 구성 요소를 만들어 보겠습니다.
네트워크 메니저를 만들고 전송방식을 선택하기
이 구역에서 우리는 Network Manager 와 Unity Transport (UTP) 컴포넌트를 프로젝트에 추가 해 보겠습니다.
- 유니티 창의 Hierarachy 탭에서 마우스 오른쪽을 클릭합니다.
- Create Empty를 선택합니다.
GameObject
로 표시된 오브젝트가 생성 되었을 것입니다. 이를 NetworkManager로 바꾸세요.
💡 팁GameObject
를 다음과 같은 사유로 바꿨습니다.
- 나중에 찾기 쉽게 만들어 줍니다.
- 이 오브젝트는NetworkManager
컴포넌트를 포함한 오브젝트로, 반드시 한개만 존재해야 합니다. 한개 이상일 경우 의도치 못한 결과를 얻을 수 있습니다.- 3번에서 만든 NetworkManager를 Hierachy에서 1회 클릭하여 선택합니다.
- Inspector(인스펙터) 탭에서 Add Component 버튼을 클릭 합니다.
- 보여진 리스트에서 Netcode를 클릭 합니다.
- 표시된 목록에서
NetworkManager
를 선택합니다. NetworkManager
컴포넌트의 탭에서NetworkTransport
필드(항목)을 찾습니다.- Select Transport 를 클릭합니다.
UnityTransport
를 선택합니다.- 씬을 저장합니다.
연결된 각 플레이어에 대해 생성할 오브젝트 만들기
이 구역에서는 플레이어 오브젝트(프리팹)를 추가하고 연결된 각 플레이어에 대한 개체를 생성해 보겠습니다.
- 유니티창의 Hierachy(하이어라키) 탭에서 마우스 오른쪽 클릭을 하여 3D 캡슐(Capsule) 오브젝트를 소환합니다.
- Player로 이름을 변경합니다.
- Player를 선택 후, Inspector(인스펙터) 탭에서 Add Component 버튼 클릭, Netcode 항목의
NetworkObject
컴포넌트를 선택하여 추가합니다. - Project(프로젝트) 탭에서 Assets 폴더를 클릭하여 열도록 합니다.
- Assets 폴더에서 마우스 오른쪽 클릭으로 표시된 메뉴에서 Create → Folder 로 폴더를 생성하고 이 폴더를 Prefabs 로 이름짓습니다.
- 1에서 만들었던 Player 오브젝트를 5에서 만들었던 폴더에 드래그&드롭 함으로서 프리팹으로 만듭니다.
- 씬에서 Player오브젝트를 지웁니다.(프리팹을 지우는게 아닙니다.)
💡 팁
이 네트워크 Prefab을NetworkManager
구성 요소의Player Prefab
속성에 할당하기 때문에 플레이어 개체를 장면에서 제거합니다. 라이브러리는 플레이어 오브젝트를 씬에 배치된NetworkObject
로 정의하는 것을 지원하지 않습니다. - NetworkManager를 선택합니다.
NetworkManager
의 컴포넌트 탭(인스펙터)에서NetworkPrefabs
필드(항목)을 찾아봅시다.+
를 클릭하여 새로운 슬롯을 하나 만듭니다.- 새로 만든 슬롯에 Player 프리팹을 드래그합니다.
- 프리팹을 Player Prefab 항목에도 드래그합니다.(Player Prefab은 NetworkPrefabs 항목 위에 있습니다.)
❗ 중요
프리팹을Player Prefab
슬롯에 놓으면 클라이언트가 게임에 연결할 때 자동으로 이 Prefab을 연결 클라이언트의 캐릭터로 생성하라는 메시지가 라이브러리에 전달됩니다. 플레이어 프리팹으로 설정된 프리팹이 없으면 플레이어 개체가 생성되지 않습니다. - 하이어라키에서 3D Object → Plane 으로 (0,0,0) 좌표에 바닥을 생성합니다.
- 씬을 저장합니다.
방금 만든 씬을 빌드에 포함시키기
❗ 중요
'Enable Scene Mangement`가 NetworkManager에 대해 활성화되어 있으면(서버가 클라이언트에 대해 로드할 씬을 제어 할 수 있음) 현재 장면이 빌드에 추가 되었는지 확인해야 합니다. 그렇지 않으면 플레이모드로 들어갈 수 없습니다. 이 옵션은 기본으로 활성화 되어 있습니다.
- 유니티 창 왼쪽 상단의 메뉴바에서 File → Build Settings 를 클릭합니다.
- Add Open Scenes 를 클릭합니다.
Build Settings
창을 닫습니다.
커맨드라인 도우미 생성
이 명령줄 도우미는 유니티 프로그램 밖에서 우리의 프로그램을 실행할 수 있게 함으로서 빌드를 테스팅하기 쉽게 만들어 줄 것입니다.
- Assets 폴더에서 마우스 오른쪽 클릭으로 표시된 메뉴에서 Create → Folder 로 폴더를 생성하고 이 폴더를 Scripts로 이름짓습니다.
NetworkCommandLine
라는 이름으로 Scripts 폴더에서 마우스 오른쪽 클릭 후 C# Script를 선택하여 만듭니다.- Hierachy(하이어라키) 창에서
NetworkManager
를 마우스 오른쪽 클릭하고, Create Empty를 선택합니다.
이 작업으로 비어있는GameObject
가NetworkManager
를 부모로 하는 비어있는 오브젝트가 생성될 것입니다. - 3번에서 만든
GameObject
를NetworkCommandLine
으로 이름을 변경합니다. - 위에서 만든
NetworkCommandLine
오브젝트를 클릭하여 선택하고 Inspector에서 Add Component 버튼을 누릅니다. - 2번에서 만들었던
NetworkCommandLine.cs
를 검색하여 컴포넌트로 추가합니다. - 2번에서 만들었던
NetworkCommandLine.cs
를 더블클릭하여 엽니다.(프로젝트탭의 Assets 폴더에서 Scripts 파일에 만들었던 스크립트) - 아래와 같이
NetworkCommandLine.cs
파일에 코드를 작성합니다. (아래의 코드 펼치기 클릭) - 작성한 코드를 저장하세요. 에디터로 돌아 오면 자동으로 새로고침될 것입니다.
- 에디터에 돌아왔다면 유니티 에디터 왼쪽 상단에 존재하는 메뉴바에서 File → Build Settings → Player Settings… 를 선택합니다. Settings for PC, Mac, & Linux Standalone 밑에 존재하는 Resolution and Presentation 을 클릭하여 영역을 확장합니다.
- Resolution 범주의 Full Screen Mode 를
Fullscreen Window
를Windowed
로 변경합니다. - 에디터 화면으로 돌아와 씬을 저장합니다.
💡 팁
유니티 프로 라이선스를 사용하고 계시다면 Splash Image → Splash Screen → Show Splash Screen 항목의 선택을 해제하여 스플래쉬 화면을 비활성화 할 수 있습니다.
using System.Collections.Generic;
using Unity.Netcode;
using UnityEngine;
public class NetworkCommandLine : MonoBehaviour
{
private NetworkManager netManager;
void Start()
{
netManager = GetComponentInParent<NetworkManager>();
if (Application.isEditor) return;
var args = GetCommandlineArgs();
if (args.TryGetValue("-mlapi", out string mlapiValue))
{
switch (mlapiValue)
{
case "server":
netManager.StartServer();
break;
case "host":
netManager.StartHost();
break;
case "client":
netManager.StartClient();
break;
}
}
}
private Dictionary<string, string> GetCommandlineArgs()
{
Dictionary<string, string> argDictionary = new Dictionary<string, string>();
var args = System.Environment.GetCommandLineArgs();
for (int i = 0; i < args.Length; ++i)
{
var arg = args[i].ToLower();
if (arg.StartsWith("-"))
{
var value = i < args.Length - 1 ? args[i + 1].ToLower() : null;
value = (value?.StartsWith("-") ?? false) ? null : value;
argDictionary.Add(arg, value);
}
}
return argDictionary;
}
}
커맨드라인 도우미 테스트하기
이제 커맨드라인 도우미가 잘 작동하는지 테스트 해 보겠습니다.
- 유니티 에디터 상단의 메뉴바에서 File → Build and Run을 선택합니다.
- 빌드파일 저장 위치를 물어보는 대화창이 표시되면 여러분의 프로젝트의 Assets 폴더에
Build
라는 이름으로 폴더를 생성하세요. - 빌드결과물(바이너리 파일)의 이름을 HelloWorld로 지정하고 저장하세요.
- 여러분의 프로젝트는 빌드 된 후 자동으로 실행되어 새로운 창의 표시화 함께 확인하실 수 있으며, 게임 화면 중앙에 평면(Plane)이 표시 될 것입니다.
- 4에서 실행된 앱을 종료합니다.
- 이제 커맨드라인에서 실행 해 봅시다. (OS별로 실행 방법이 다릅니다. 아래 더보기를 클릭 해 주세요)
윈도우에서 해야 할 일 :
- 명령줄 도구 프로그램을 실행하세요. (윈도우키 + R 단축키 사용 후 cmd를 검색하여 실행)
- 아래 도움말을 따라하세요.
< >
를 사용한 부분은 여러분의 프로젝트 위치로 변경하여 사용합니다.
💡 팁
유프로그램을 실행할지 말지에 대한 사용 권한을 물어 보는 창이 표시 될 수 있으며, 이를 허용하셔야 합니다.
서버 :
<프로젝트파일 위치>\Build\HelloWorld.exe -mlapi server
클라이언트 :
<프로젝트 파일 위치>\Build\HelloWorld.exe -mlapi client
위의 코드를 한번에 실행하기 :
HelloWorld\Build\HelloWorld.exe -mlapi server & HelloWorld\Build\HelloWorld.exe -mlapi client
사용 예시 :
C:\Users\sarao>HelloWorld\Build\HelloWorld.exe -mlapi server & HelloWorld\Build\HelloWorld.exe -mlapi client
❗ 중요
윈도우에서는 기본적으로 표준 출력 스트림(standard out stream)이 없으므로 출력을 보려면 Debug.log 파일을 확인해야 합니다. Debug.log파일은 다음 위치에서 확인 할 수 있습니다.C:\Users\<사용자명>\AppData\LocalLow\CompanyName\ProductName\Player.log
여기서 CompanyName은 기본적으로 DefaultComapny로 되어 있으며, 새 프로젝트에선 ProductName은 프로젝트명입니다.
또는 윈도우 명령어를 수정하여 프로젝트 폴더와 같은 위치에 로그를 남기도록 수정하실 수 있습니다.
서버:
<프로젝트 폴더 위치>\Build\HelloWorld.exe -logfile log-server.txt -mlapi server
클라이언트 :
<프로젝트 폴더 위치>\Build\HelloWorld.exe -logfile log-client.txt -mlapi client
사용 예시 :
C:\Users\sarao>HelloWorld\Build\HelloWorld.exe -logfile -log-server.txt -mlapi server & HelloWorld\Build\HelloWorld.exe -logfile log-client.txt -mlapi client
맥에서는 다음과 같이 실행해야 합니다.
- 터미널을 엽니다.
- 아래 도움말을 따라하세요. < > 를 사용한 부분은 여러분의 프로젝트 위치로 변경하여 사용합니다.
서버 :
<프로젝트 폴더 위치>/Build/HelloWorld.app/Contents/MacOS/<프로젝트 명> -mlapi server -logfile -
클라이언트 :
<프로젝트 폴더 위치>/Build/HelloWorld.app/Contents/MacOS/<프로젝트 명> -mlapi client -logfile -
위의 두개를 하나의 커맨드로 실행하기 :
<프로젝트 파일 위치>/Build/HelloWorld.app/Contents/MacOS/<프로젝트 명> -mlapi server -logfile - & ; ~ <프로젝트 폴더 위치>/Build/HelloWorld.app/Contents/MacOS/<프로젝트 명> -mlapi client -logfile -
Hello World 테스트 하기
이제 모두 잘 작동하는지 테스트 해 보겠습니다.
- 에디터에서 Play ▶ 버튼을 클릭합니다.
- NetworkManager에서 Start Host 버튼을 클릭합니다.
다음 단계
Netcode를 사용하는 여정을 계속하시려면 아래 콘텐츠들을 참조하시길 바랍니다.
- Hello World 프로젝트에 Netcode를 사용한 다른 기능들을 공부하며 추가하고 싶으시다면 골든 패스 시리즈를 봐주세요.
- 교육용 샘플과 더 많은 Netcode의 가능성을 알고 싶으시다면 아래를 참고해 주세요.