[멋사 부트캠프 TIL회고] 오목 멀티플레이 오류 수정(2)
잡다한 오류들
1. 자동 닉네임 설정 오류
닉네임이 서버로 제대로 들어오나 ( 자동 닉네임 설정 ) DB에 제대로 반영되지 않는 문제
-> 오타 수정으로 해결 완료
2. roomId가 rooms 배열에 남아 있어 빈 방에 들어가지는 문제
현재 아래와 같은 방식으로 매칭된 방은 rooms에서 삭제해 주고 있고, 게임이 끝나면 둘 다 나가지기에 자동으로 삭제됨
그러나, 한 명이 매칭 중에 화면을 나갔을 때는 방에 아무도 남아 있지 않게 되어 방이 삭제되긴 하나
roomId는 그대로 rooms 배열에 남아 있는다. 따라서 새로운 사람이 매칭을 시작하면 그 roomId의 방으로 진입을 시도하고
없는 roomId이기에 새로운 방을 만들게 된다 ( 같은 roomId의 ) . 다만 우리의 코드가 rooms 배열에 있는 room으로 진입을 했을 때에 자동으로 게임이 시작되게 만들어 두었기 때문에 빈 방에서 게임을 시작하게 되는 오류가 발생했다.
따라서 위와 같이, disconnect 할 때 ( 매칭 중이다 나갈 때 ) 모든 방을 검사하여 빈 방이 있다면 삭제했다.
효율성의 문제가 있을 수 있지만, 우선 rooms 배열은 '매칭 중'인 방들만을 의미하기 때문에 대규모 게임이 아닌 이상
수천, 수만이 될 수 없고 수백까지의 배열 순회는 큰 리소스를 잡아먹지 않기에 이렇게 간단하게 작성했다.
기능 추가
1. 암호화 기능 추가
간단하게 모듈을 사용해서 암호화 기능을 추가했다.
2. 정규식 표현으로 이메일 형식만 받음 .
3. 유저 정보 수정
들어온 유저 정보만 바꿀 수 있는 함수를 제작했다.
이렇게 가져오기 위해서는 데이터 타입에서 int를 nullable로 만들어 주어야 한다.
그렇지 않고 그냥 int type으로 하게 된다면, 기본값인 0이 할당되게 되어 원하지 않는 결과가 나온다.
[Serializable]
public struct ReviseUserData
{
public string userId;
public string nickname;
public int? coin;
public int? grade;
public int? gradeScore;
// public int win;
// public int draw;
// public int lose;
public int? profileIndex;
}
nullable 타입은 Unity에서 기본적으로 제공하는 파서로는 파싱이 힘들기 때문에
newtonsoft에서 제공하는 파서를 사용해야 한다.
string jsonString = JsonConvert.SerializeObject(reviseUserData,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
이렇게 파싱하면, Null 변수는 전송되지 않는다.
4. 랭킹 가져오기
테스트 용도로 이렇게 만들었다.
아직 클라이언트 쪽에서 받는 코드가 생기려면 좀 멀어서 그냥 혼자 테스트 해 볼 예정이다.
테스트 성공 ~
조금 헤맸다. 배열 형태로 전달하는데 리스트 형태로 받는다
[System.Serializable]
public class Ranking
{
public List<RankingData> ranking;
}
[System.Serializable]
public class RankingData
{
public string nickname;
public int grade;
public int gradeScore;
public int profileIndex;
public int win;
public int draw;
public int lose;
}
public IEnumerator GetGradeRanking(Action success, Action failure)
{
using (UnityWebRequest www =
new UnityWebRequest(Constants.ServerURL + "users/getGradeRanking", UnityWebRequest.kHttpVerbGET))
{
www.downloadHandler = new DownloadHandlerBuffer();
yield return www.SendWebRequest();
if (www.result == UnityWebRequest.Result.ConnectionError ||
www.result == UnityWebRequest.Result.ProtocolError)
{
Debug.Log("Error: " + www.error);
failure?.Invoke();
}
else
{
var resultString = www.downloadHandler.text;
var gradeRanking = JsonConvert.DeserializeObject<Ranking>(resultString);
Debug.Log("1");
}
}
}
public IEnumerator GetWinLossRanking(Action success, Action failure)
{
using (UnityWebRequest www = new UnityWebRequest(Constants.ServerURL + "users/getWinLossRanking",
UnityWebRequest.kHttpVerbGET))
{
www.downloadHandler = new DownloadHandlerBuffer();
yield return www.SendWebRequest();
if (www.result == UnityWebRequest.Result.ConnectionError ||
www.result == UnityWebRequest.Result.ProtocolError)
{
Debug.Log("Error: " + www.error);
failure?.Invoke();
}
else
{
var resultString = www.downloadHandler.text;
var winLossRanking = JsonConvert.DeserializeObject<Ranking>(resultString);
Debug.Log("1");
}
}
}
문제 : 같은 프레임에 두 개의 UnityWebRequest를 요청하면 하나만 실행되는 문제
1. 기본적으로는 코루틴으로 실행하기 때문에 여러 개의 UnityWebRequest가 동시에 수 있다.
다만, 유니티의 네트워크 요청 처리 방식과 코루틴의 실행 방식이 겹치면서 충돌이 발생할 가능성이 높다.
2. UnityWebRequest는 비동기적으로 동작하지만, 특정 조건에서 실행이 중단될 수 있다.
이와 같은 가능성이 있다.