-
07/27 nodejs + Unity연동 (UnityWebRequest)게임 네트워크 프로그래밍 2021. 7. 27. 13:26
ranking-server폴더 만들기
폴더 안에서
npm init -y
npm i express
코드 작성
app.js
const express = require('express'); const app = express(); app.get('/', (req, res) => { res.send('hello world!'); }); app.listen(3030, () => { console.log('server is running at 3030 port.'); })
점수 입력하는 라우터
const express = require('express'); const app = express(); let users = {}; app.use(express.json()); app.get('/', (req, res) => { res.send('hello world!'); }); app.post('/score', (req, res) => { const { id, score} = req.body; users[id] = score; console.log(users); res.status(200).end(); }); app.listen(3030, () => { console.log('server is running at 3030 port.'); })
최종 코드
API 설명
POST : /scores
{ id, score }
점수를 등록하거나 갱신
GET : /scores/top3
{ cmd, message, result }
result : Array
GET : /scores/id
해당 id의 유저 점수를 얻어 옵니다.
{ cmd, message, result }
result : Objectconst express = require('express'); const app = express(); let users = []; app.use(express.json()); app.get('/', (req, res)=>{ res.send('hello world!'); }); app.post('/scores', (req, res)=>{ const { id, score } = req.body; let result = { cmd: -1, message: '' }; let user = users.find(x=>x.id == id); if( user === undefined){ //아직 등록이 한번도 안된 유저 신규 등록 users.push( { id, score } ); result.cmd = 1001; result.message = '점수가 신규 등록 되었습니다.'; }else{ console.log(score, id, user.score); if( score > user.score){ //등록 하려고 하는 점수가 저장된 점수보다 크다면 갱신 user.score = score; result.cmd = 1002; result.message = '점수가 갱신 되었습니다.'; }else{ result.cmd = 1003; } } console.log(users); res.send(result); }); app.get('/scores/top3', (req, res)=>{ let result = users.sort(function (a, b) { return b.score - a.score; }); result = result.slice(0, 3); // 0 ~ n-1 res.send({ cmd: 1101, message: '', result }); }); app.get('/scores/:id', (req, res)=>{ console.log('id: ' + req.params.id); let user = users.find(x=>x.id == req.params.id); if(user === undefined){ res.send({ cmd: 1103, message: '잘못된 id입니다.', }); }else{ res.send({ cmd: 1102, message: '', result: user }); } }); app.listen(3030, ()=>{ console.log('server is running at 3030 port.'); });
ScriptableObject
https://docs.unity3d.com/kr/2019.4/Manual/class-ScriptableObject.html
ScriptableObject - Unity 매뉴얼
ScriptableObject는 클래스 인스턴스와는 별도로 대량의 데이터를 저장하는 데 사용할 수 있는 데이터 컨테이너입니다. ScriptableObject의 주요 사용 사례 중 하나는 값의 사본이 생성되는 것을 방지하
docs.unity3d.com
using UnityEngine; [CreateAssetMenu(fileName = "Data", menuName = "ScriptableObjects/SpawnManagerScriptableObject", order = 1)] public class SpawnManagerScriptableObject : ScriptableObject { public string id; public int score; }
RankMain.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using Newtonsoft.Json; using UnityEngine.Networking; using System.Text; public class RankMain : MonoBehaviour { public string host; public int port; public string top3Uri; public string idUri; public string postUri; public SpawnManagerScriptableObject scriptableObject; public Button btnGetTop3; public Button btnGetId; public Button btnPost; void Start() { this.btnGetTop3.onClick.AddListener(() => { var url = string.Format("{0}:{1}/{2}", host, port, top3Uri); Debug.Log(url); StartCoroutine(this.GetTop3(url, (raw) => { var res = JsonConvert.DeserializeObject<Protocols.Packets.res_scores_top3>(raw); Debug.LogFormat("{0}, {1}", res.cmd, res.result.Length); foreach (var user in res.result) { Debug.LogFormat("{0} : {1}", user.id, user.score); } })); }); this.btnGetId.onClick.AddListener(() => { var url = string.Format("{0}:{1}/{2}", host, port, idUri); Debug.Log(url); StartCoroutine(this.GetId(url, (raw) => { var res = JsonConvert.DeserializeObject<Protocols.Packets.res_scores_id>(raw); Debug.LogFormat("{0}, {1}", res.result.id, res.result.score); })); }); this.btnPost.onClick.AddListener(() => { var url = string.Format("{0}:{1}/{2}", host, port, postUri); Debug.Log(url); //http://localhost:3030/scores var req = new Protocols.Packets.req_scores(); req.cmd = 1000; //(int)Protocols.eType.POST_SCORE; req.id = scriptableObject.id; req.score = scriptableObject.score; //직렬화 (오브젝트 -> 문자열) var json = JsonConvert.SerializeObject(req); Debug.Log(json); //{"id":"hong@nate.com","score":100,"cmd":1000} StartCoroutine(this.PostScore(url, json, (raw) => { Protocols.Packets.res_scores res = JsonConvert.DeserializeObject<Protocols.Packets.res_scores>(raw); Debug.LogFormat("{0}, {1}", res.cmd, res.message); })); }); } private IEnumerator GetTop3(string url, System.Action<string> callback) { var webRequest = UnityWebRequest.Get(url); yield return webRequest.SendWebRequest(); if (webRequest.result == UnityWebRequest.Result.ConnectionError || webRequest.result == UnityWebRequest.Result.ProtocolError) { Debug.Log("네트워크 환경이 안좋아서 통신을 할수 없습니다."); } else { callback(webRequest.downloadHandler.text); } } private IEnumerator GetId(string url, System.Action<string> callback) { var webRequest = UnityWebRequest.Get(url); yield return webRequest.SendWebRequest(); Debug.Log("--->" + webRequest.downloadHandler.text); if (webRequest.result == UnityWebRequest.Result.ConnectionError || webRequest.result == UnityWebRequest.Result.ProtocolError) { Debug.Log("네트워크 환경이 안좋아서 통신을 할수 없습니다."); } else { callback(webRequest.downloadHandler.text); } } private IEnumerator PostScore(string url, string json, System.Action<string> callback) { var webRequest = new UnityWebRequest(url, "POST"); var bodyRaw = Encoding.UTF8.GetBytes(json); //직렬화 (문자열 -> 바이트 배열) webRequest.uploadHandler = new UploadHandlerRaw(bodyRaw); webRequest.downloadHandler = new DownloadHandlerBuffer(); webRequest.SetRequestHeader("Content-Type", "application/json"); yield return webRequest.SendWebRequest(); if (webRequest.result == UnityWebRequest.Result.ConnectionError || webRequest.result == UnityWebRequest.Result.ProtocolError) { Debug.Log("네트워크 환경이 안좋아서 통신을 할수 없습니다."); } else { Debug.LogFormat("{0}\n{1}\n{2}", webRequest.responseCode, webRequest.downloadHandler.data, webRequest.downloadHandler.text); callback(webRequest.downloadHandler.text); } } }
Protocols.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Protocols { public class Packets { public class common { public int cmd; } public class req_scores : common { public string id; public int score; } public class res_scores : common { public string message; } public class user { public string id; public int score; } public class res_scores_top3 : res_scores { public user[] result; } public class res_scores_id : res_scores { public user result; } } }
점수 등록
순위 출력
id로 점수 검색
asdf유저 점수 검색 '게임 네트워크 프로그래밍' 카테고리의 다른 글
07/26 Assetbundle 에셋번들 (0) 2021.07.26 07/20 포톤 서버 사용 (0) 2021.07.20