ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 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 : Object

     

    const 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
Designed by Tistory.