유니티와 서버 통신을 하는 것이다.
먼저 express 서버를 만든다.
새로운 서버 만들기
폴더 들어가서 초기화 해주고
익스프레스와 노드몬 설치
app.js 만들어서
기본 3030 포트 서버를 만들어준다.
실행
정상 작동함
----
랭킹 서버를 만들 것이다.
먼저 스코어 라우터를 만들어서
바디에서 id 와 score를 받아준다.
res.로 200 찍어주고, end() 를 꼭 해줘야한다.
엔드 안하면 무한 루프
정상적으로 찍힘
저렇게 넣으면 딕셔너리 처럼 , 키 : 밸류 형식으로 넣을 수 있음 ! 꿀팁!
키 밸류기 때문에 키만 넣어줘도, 밸류 값이 나옴 ㅇㅇ
const express = require('express');
const app = express();
let users = {};
app.use(express.json());
app.get('/', (req, res) => {
res.send('hello');
});
app.post('/score', (req, res) => {
const {id, score} = req.body;
let result = {
cmd: -1,
message: ''
}
if(users[id] === undefined){
//아직 등록이 한번도 안된 유저 신규 등록
users[id] = score;
result.cmd = 1001;
result.message = '점수가 신규 등록 되었습니다.';
}
else{
if(score > users[id]){ //등록 하려고 하는 점수가 저장된 점수보다 크다면 갱신
users[id] = score;
result.cmd = 1002;
result.message = '점수가 갱신 되었습니다.';
}
else{
result.cmd = 1003;
}
}
console.log(users);
res.send(result);
})
app.listen(3030, () => {
console.log("3030 server on");
});
신규 등록
점수 갱신
갱신이 아닌 그냥 점수일때
----
키 밸류 사용 방법도 좋지만
배열로 해야 나중에 역직렬화 하기도 편해서
위에 users 를 배열로 바꿔준다.
const express = require('express');
const app = express();
let users = [];
app.use(express.json());
app.get('/', (req, res)=>{
res.send('hello express!');
});
app.post('/score', (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.listen(3030, ()=>{
console.log('server is running at 3030 port.');
});
일단 배열로 이어서 한다.
---
테스트 .js 만들어서 테스트한다.
저장된 배열 솔트 (정렬) 하는 것 내림 차순
배열의 0~2 인덱스 반환한다.
const { restart } = require("nodemon");
var users = [
{id : 'min@gaga', score: 200},
{id : 'mddd@gaga', score: 100},
{id : '111@gaga', score: 300},
{id : 'rrrrr@gaga', score: 500},
{id : 'qqqq1@gaga', score: 700},
]
var result;
result = users.sort(function(a,b) {
return b.score - a.score;
})
result = result.slice(0,3); // 0 ~ 2 // =
console.log(result);
이걸 가져다가 쓴다.
app.js
추가 해준다.
const express = require('express');
const { restart } = require('nodemon');
const app = express();
let users = [];
app.use(express.json());
app.get('/', (req, res)=>{
res.send('hello express!');
});
app.post('/score', (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);
res.send({
cmd: 1101,
message: '',
result
});
});
app.get('/scores/:id', (req,res) => {
});
app.listen(3030, ()=>{
console.log('server is running at 3030 port.');
});
포스트맨에서
4개 넣어준다.
get 스코어스 하면 3등까지 나온다.
이제 아이디를 쿼리로 검색할 수있는 것 추가
const express = require('express');
const app = express();
let users = [];
app.use(express.json());
app.get('/', (req, res)=>{
res.send('hello express!');
});
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.');
});
전체 코드
검색 가능
기본적인 API 서버 완성
---
유니티 프로젝트 만들기
API : https://docs.unity3d.com/kr/2020.3/Manual/UnityWebRequest.html
유니티 메뉴얼
먼저
json.net 인풋해주기
(dll 오류 뜨면 폴더하나 지우기)
UI 만들기
스크립터 만들기
RankMain 만들어서
넣어주기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class RankMain : MonoBehaviour
{
public string host;
public int port;
public string top3Uri;
public string idUri;
public string postUri;
public Button btnGetTop3;
public Button btnGetId;
public Button btnPost;
// Start is called before the first frame update
void Start()
{
this.btnGetTop3.onClick.AddListener(() => {
var url = string.Format("{0}:{1}/{2}", host, port, top3Uri);
Debug.Log(url);
});
this.btnGetId.onClick.AddListener(() => {
var url = string.Format("{0}:{1}/{2}", host, port, idUri);
Debug.Log(url);
});
this.btnPost.onClick.AddListener(() => {
var url = string.Format("{0}:{1}/{2}", host, port, postUri);
Debug.Log(url);
});
}
// Update is called once per frame
void Update()
{
}
}
준비완료
패킷 클래스 설계 / 또는 구조체 설계
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Protocols
{
public enum eType {
POST_SCORE = 1000
}
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;
}
}
}
---
스크립터블 오브젝트 활용
https://docs.unity3d.com/kr/2019.4/Manual/class-ScriptableObject.html
스크립터 만들어주기
SpawnManagerScriptableObject.cs
ing UnityEngine;
[CreateAssetMenu(fileName = "Data", menuName = "ScriptableObjects/SpawnManagerScriptableObject", order = 1)]
public class SpawnManagerScriptableObject : ScriptableObject
{
public string prefabName;
public int numberOfPrefabsToCreate;
public Vector3[] spawnPoints;
}
저게 생긴다.
테스트를 해보니 잘 만들어진다.
이제 우리 걸로 만들어준다.
우리가 뚫을 퍼블릭 값을 넣고
만들어주면
값을 넣을수있다.
이제 퍼블릭으로
뚫어서 넣고
이제 저 스크립타블 오브젝트에 있는 값을 이용할 수있다 .
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Newtonsoft.Json;
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);
});
this.btnGetId.onClick.AddListener(() => {
var url = string.Format("{0}:{1}/{2}", host, port, idUri);
Debug.Log(url);
});
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}
});
}
}
포스트 할 준비 끝
전체 추가 코드
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);
});
this.btnGetId.onClick.AddListener(() => {
var url = string.Format("{0}:{1}/{2}", host, port, idUri);
Debug.Log(url);
});
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 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);
}
}
}
플레이해서 등록하면
포스트가 되는 것
서버에서 날라옴
바꿔주고
등록하면
추가 등록이 댐
----
get 해보기
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);
});
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 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);
}
}
}
나온다.
----
id로 검색하기
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);
}
}
}
검색 되었다..
'Unity > 서버' 카테고리의 다른 글
210722_ AdMob _구글 애드몹 유니티에 달기 (0) | 2021.07.22 |
---|---|
210722_ 유니티Ads (0) | 2021.07.22 |
210721_ IAP (인앱결제) (0) | 2021.07.21 |
210720_ 포톤 서버 (시험) (5) | 2021.07.20 |
210714 _ 데이터 프로그래밍 2 (복습 및 시험) (0) | 2021.07.14 |