▶ 본 시리즈로 만들어진 실제 시스템 [Inhaverse]
└ 시스템에 탑재된 PlayFab Manager 스크립트 전문
Unity로 멀티플레이 게임을 개발할 때 벡앤드 개발은 필수적이다. 필자는 학부 졸업프로젝트으로 메타버스 시스템을 선택하였으며, 데이터 처리를 위한 백엔드 플랫폼으로 PlayFab
을 선택하였다.
PlayFab은 자체적으로 유저 정보를 관리하는 시스템을 제공한다. 회원가입, 로그인 등을 위한 함수가 마련되어 있고, 계정에 저장할 유저 정보 타입을 선택할 수 있다. 또한 특정 유저가 속한 그룹, 유저가 가진 재화의 정보, 전체 유저를 대상으로 항목별 순위를 매기는 대시보드 등의 기능을 제공한다.
다만 국내 PlayFab 사용자 수가 많지 않아 활용할 자료가 많지 않다. 필자가 공식 문서와 스택오버플로우 등에서 긁어낸 정보가 아까워서 공유하고자 이렇게 포스팅을 작성한다.
하지만 커뮤니티를 메인으로 하는 메타버스 시스템에서 PlayFab은 썩 좋은 선택은 아니었다. 필자의 시스템은 학교 캠퍼스를 온라인에 구현하여 그 안에서 수업도 듣고 커뮤니티 활동도 할 수 있도록 하고자 하였는데, 어떤 학생이 어떤 수업을 듣고 출결 정보를 저장하거나 과제 제출 등에 대한 데이터를 저장하는 데 적절한 플랫폼이 아니었다. 물론 필자가 PlayFab을 완전히 이해하지 못해 이런 어려움을 겪은 것일 수 있지만, 이미 개발에 착수한 후라 뒤늦게 백엔드 시스템을 교체하기에 무리가 있다고 판단해 요령껏 기능을 구현하였다. 이 점을 유의하자.
PlayFab은 Entity
를 단위로 데이터를 관리한다. Entity
는 유니티 엔진에 비유하면 GameObject
와 비슷한 역할을 한다고 보면 된다. 씬에 배치되는 모든 요소가 GameObject
로 취급되는 것처럼, 데이터를 저장하는 모든 주체들은 Entity
라는 단위로 관리된다.
특정 유저에 대한 정보는 Client Entity
, 그룹에 대한 정보는 Group Entity
와 같이 구분되어 모든 Entity
는 고유한 ID와 용도에 따라 조금씩 다른 파라미터를 가진다.
PlayFab의 API는 병렬로 처리된다. 일반적인 프로그래밍 언어에선 함수를 호출하면 프로세서가 해당 함수를 타겟하여 순서에 따라 명령을 실행하고 반환 후 함수를 호출했던 위치로 돌아가 다음 명령을 수행하지만, PlayFab의 API는 호출하고 바로 다음 라인으로 넘어가 코드를 수행한다. 즉, API의 처리와 작성한 코드의 처리가 병렬적으로 수행된다는 것이다.
이것이 왜 중요하냐면, 예를 들어 API로 학생 플레이어의 정보를 불러온다고 하자. 그리고 불러온 데이터를 UI에 출력해줄 것이다.
public void GetMyInfo()
{
var request = new GetAccountInfoRequest { PlayFabId = myPlayfabId };
PlayFabClientAPI.GetAccountInfo(request,
(result) =>
{
playerName = result.AccountInfo.TitleInfo.DisplayName;
playerSchoolId = result.AccountInfo.Username;
Debug.Log("불러오기 성공, 이름 : " + playerName + ", 학번 : " + playerSchoolId);
}, (error) => Debug.Log("정보 불러오기 실패"));
UIManager.Instance.UIInitFromPlayfabLogin(playerName, playerSchoolId);
}
계정의 타이틀 정보를 위한 GetAccoutInfo라는 함수를 호출하여 DisplayName
, Username
등을 얻을 수 있다. 이 정보를 UIInitFromPlayfabLogin()
함수에 전달하여 UI를 업데이트하는 것이 목적일 때, 위에서 말한 특징이 의도치 않은 결과를 만든다.
API를 호출하여 PlayFab 서버에 접근해 데이터를 불러오는 시간이 필요한데, PlayFab API는 호출 후 데이터를 불러오기에 성공했는지 실패했는지 확인하지 않고 다음 코드를 실행하기 시작한다. 즉, 데이터를 불러오지 않았는데 UIInitFromPlayfabLogin()
함수를 호출하게 되는 것이다. playerName
, playerSchoolId
변수에는 서버로부터 가져온 올바른 정보가 아직 저장되지 않았는데 이를 매개변수로 전달하여 함수를 실행하기 때문에 적절하지 않은 값으로 UI가 초기화될 수 있다.
따라서 API의 결과로 얻어낸 정보를 이용할 것이라면 result
안에 처리 코드를 삽입해주어야 한다. 올바르게 처리되는 코드는 아래와 같다.
public void GetMyInfo()
{
var request = new GetAccountInfoRequest { PlayFabId = myPlayfabId };
PlayFabClientAPI.GetAccountInfo(request,
(result) =>
{
playerName = result.AccountInfo.TitleInfo.DisplayName;
playerSchoolId = result.AccountInfo.Username;
UIManager.Instance.UIInitFromPlayfabLogin(playerName, playerSchoolId);
Debug.Log("불러오기 성공, 이름 : " + playerName + ", 학번 : " + playerSchoolId);
}, (error) => Debug.Log("정보 불러오기 실패"));
}
result
가 호출되면 그 내부에서 순차적으로 코드를 실행하기 때문에 playerName
과 playerSchoolId
를 정상적으로 불러온 후 이를 활용할 수 있게 된다.
앞으로 살펴볼 모든 API가 이와 같은 시스템으로 동작하므로 반드시 유의하자.