1. 유니티 + Nodejs를 활용한
멀티플레이어 게임 개발하기
-최대한 간단하게-
KIYOUNG MOON
2017-07-10
2. Node.js
Node.js는 서버사이드에서 자바스크립트로 응용 프로그램을 만들 수 있게
해준다.
Module 기능을 사용해 이미 만들어진/다른 사람이 만든 모듈을 재사용할
수 있다.
Express
Forever
Socket.io
등등
매우 짧은 코드로 서비스 가능한 응용 프로그램을 만들 수 있다.
3. Node.js를 활용한 프로젝트들
Yammer
Linkedin
http://browserquest.mozilla.org/
그 외에 모바일 앱을 위한 서버들…
11. Nodejs로 만들면…
http를 사용하기 위해 모듈을 가져온다.
var http = require(‘http’);
var server = http.createServer(
function(request, response) {}
);
12. 파일 읽기
var fs = require(‘fs’);
fs.readFile(‘image.png’,
function(error, data) { }
);
읽혀진 데이터는 data로 넘어온다.
13. 오늘의 짤 서비스를 만들어 보자.
웹브라우저로 접근하면 오늘의 짤을 무작위로 보여주는 웹서비스 만들기.
14. 무작위로 이미지를 보여주는 서비스를 Nodejs로 구현
var url = require('url'); // import url module.
var fs = require('fs'); // file system
var http = require('http');
var server = http.createServer(function(request, response){
response.writeHead(200, { 'Content-Type': 'image/png'});
var i = parseInt(Math.random() * 4 + 1);
fs.readFile('images/' + i + '.png', function(error, data){
response.end(data);
});
});
server.listen(3000);
15. 데디케이티드 서버(Dedicated Server)
하나의 서버 프로세스에서 게임 룸에 따라 모든 처리를 하는 것이 아니라 게
임 룸 하나당 하나의 프로세스를 생성해 처리하는 것. 이러한 서버를
Dedicated Server라 한다.
결론적으로 로비에서 방1, 방2, …, 방n과 같이 방하나가 생길 때 데디케이트
서버 프로세스가 생성되고 이 프로세스에서 클라이언트와 게임 처리를 한
다.
퀘이크(Quake), 언리얼 토너먼트(Unreal Tournament), 기어즈 오브 워
(Gears of War), LOL과 같은 게임들이 이러한 데디케이트 서버의 형태를 가
지고 있다.
16. 유니티로 데디케이트 서버 만들기
유니티에 –batchmode 커맨드 옵션을 주면 화면을 띄우지 않고 프로세스만
띄울 수 있다. 보통 서버 포트를 설정하는데 이것은 –port와 같이 문자열을
커맨드 옵션으로 주고 포트 번호만 파싱하면 된다.
무식한 방법
if (commandLineOptions.Contains("-port")) {
string[] args = System.Environment.GetCommandLineArgs();
for (int i = 0; i < args.Length; ++i) {
if (args[i].Equals("-port")) {
serverPort = Convert.ToInt32(args[i + 1]);
break;
}
}
netManager.networkPort = serverPort;
}
17. 데디케이티드 서버 배포
포트를 커맨드 옵션으로 주면 서버가 생성되는 서버를 만든다.
그리고 이 파일들을 nodejs 서버가 실행되는 경로에 저장한다.
18. Nodejs에서 외부 실행파일 실행하기
var exec = require('child_process').exec;
exec('game.exe -batchmode -port ' + dedicateServer['port'] +
' -dedicateServer ' + i, function(error, stdout, stderr)
{
});
Game.exe를 실행할 때 –batchmode 옵션을 주고 –port 7777과 같이 포트 번호를
넘겨 준다. 그 뒤에 있는 옵션은 데디 서버의 인덱스 번호다.(nodejs 서버에서 관리
되는 데디케이티드 서버 리스트 인덱스)
참고로 Unet은 udp를 사용한다! 방화벽에서 udp포트를 열어 놓아야 한다.
19. Nodejs로 서버 생성하기
var server = http.createServer(function(request, response) {
}).listen(6666, function() {
console.log('"socket io server is running at 6666');
});
http 모듈을 사용해서 서버를 만든다. 서버의 포트 번호는 6666이다.
20. Scoket.io
웹 소켓 프로그래밍을 하려면 socket.io를 사용하면 된다.
var io = socketio.listen(server);
생성된 서버로 Listen하고 클라이언트에서 웹 소켓으로 연결하면 된다.
21. 유니티에서 socket.io 사용하기
using SocketIOClient;
https://github.com/NetEase/UnitySocketIO
에서 bin에 있는 모든 파일들을 유니티
Plugins 폴더 안에 넣으면 된다.
22. 유니티에서 Nodejs 서버로 웹소켓 연결
하기using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using SocketIOClient;
public class SocketManager : MonoBehaviour {
string url = "http://127.0.0.1:6666/";
public static Client Socket
{
get; private set;
}
// Use this for initialization
void Awake()
{
GameObject.DontDestroyOnLoad(gameObject);
Socket = new Client(url);
Socket.Opened += SocketOpened;
Socket.Connect();
}
void OnDisable()
{
Socket.Close();
}
}
23. Nodejs에서 웹소켓 연결 처리
클라이언트가 연결되면 connection이 호
출 된다.
다음에 socket.on에서 이벤트를 등록해 클
라이언트에서 이벤트가 날아오면 원하는
동작을 할 수 있다.
24. 데디케이티드 서버가 만들어지고 난 후
클라이언트 연결 처리
데디 서버가 만들어지고 나면 클라이언트들이 해당 데디케이티드 서버로
접속해야 한다. 클라이언트는 서버에서 만들어진 데디케이티드 서버의 주소
와 포트 번호를 모른다.
Nodejs에서 데디 서버의 프로세스를 생성하고 포트 번호를 모든 클라이언
트에 전달한다.
25. 데디케이티드 서버가 생성이 된 후에 D2SReadyToPlay를 nodejs로 이벤트를 날린다. 그 이후
에 모든 클라이언트에 데디 서버의 포트 번호를 알려준다. 이때 사용되는 이벤트는
S2CDedicateServerPort다.
26. Nodejs 서버에서 데디케이티드 서버의 포트를 S2CDedicateServerPort로 알려
주면 클라이언트는 해당 포트로 접속하여 게임 플레이 진행 가능하다.
32. NetworkTransform 컴포넌트
게임 오브젝트의 트랜스폼을 동기화 시킨다.
품질은 매우 낮음(끊겨서 보임)
그래서… 결국은 껯, Command를 사용해 직접 구현해서 사용하는 편이 좋다.
33. Rigidbody 동기화
Transform Sync Mode를 통해 동기화 시킬 타입을 설정할 수 있다.
RigidBody의 경우 Sync Rigidbody 3D를 선택해 RigidBody를 동기화 시킬
수 있다.
품질은 Sync Transform보다는 괜찮음.
34. 위치 보간 직접 구현해버리기
SyncPlayerPos 스크립트 사용.
각 클라이언트가 현재 위치를 서버에 알린다. 서버는 해당 클라이언트에 붙
어 있는 SyncPos를 업데이트 한다. 이렇게 하면 클라이언트의 SyncPos가 업
데이트 된다.
이후에 클라이언트가 이 SyncPos로 현재 위치에서 보간 한다.