Unity 게임에 스코어보드와 리더보드를 추가하는 방법
PubNub Developer Relations
Posted on May 15, 2024
스코어보드와 순위표는 플레이어의 참여를 촉진하는 데 있어 핵심적인 요소입니다. 스코어보드는 플레이어가 치열한 대전에 참여하는 동안 중요한 정보를 제공하고 승리 가능성을 판단하는 데 필요하며, 리더보드는 경기 후 플레이어 간의 경쟁을 장려하기 위해 높은 점수를 확인하는 방법으로 사용됩니다. 두 가지 모두 리플레이를 장려하고 플레이어의 고착화를 쉽게 도울 수 있는 방법입니다.
스코어보드와 리더보드는 게임 개발에서 건전한 경쟁을 촉진하고 게임 중에 중요한 피드백을 제공하는 데 필수적이지만, Unity 프로젝트에 이러한 기능을 통합하는 것은 말처럼 쉬운 일이 아닙니다. 처음부터 시작하려면 스코어보드 업데이트를 전달하고 업데이트된 리더보드 점수를 저장해야 하므로 플레이어가 증가할 때 빌드, 유지 관리 및 확장하는 데 많은 리소스가 필요합니다. 다행히도 PubNub은 지연 시간이 짧은 실시간 API 플랫폼을 통해 그 어느 때보다 쉽게 Unity 게임에 실시간 기능을 추가할 수 있도록 지원합니다. 유니티는 앱의 인프라 계층을 관리하므로 개발자는 애플리케이션에만 집중할 수 있습니다. Windows, Mac, iOS, Android, Oculus 및 Meta Quest와 같은 가상 현실 시스템 또는 크로스 플랫폼용 개발이든, 유니티 SDK는 모든 것을 지원합니다.
이 가이드를 따라할 때 참고할 수 있도록 Unity 게임에서 스코어보드와 리더보드를 구현하는 방법의 예시를 보고 싶다면 Unity 쇼케이스 게임을 확인해 보세요.
계속 읽으면서 PubNub 게임 오브젝트를 구성하는 방법부터 PubNub 함수에 대해 알아보고, 게임의 필요에 맞게 PubNub 메시지를 파싱하는 방법까지 실시간으로 업데이트되는 스코어보드와 리더보드를 Unity 게임에 추가하는 방법을 단계별로 알아보세요.
PubNub 시작하기
Unity 게임의 스코어보드와 리더보드를 설정하는 방법을 이해하려면 먼저 PubNub에 대해 이해하고 플랫폼의 기능을 활용하도록 애플리케이션을 구성하는 방법을 알아야 합니다.
개요
PubNub는 Pub/Sub(게시/구독) 모델을 기반으로 합니다. 사용자는 기본적으로 모든 관련 정보가 포함된 페이로드인 메시지를 PubNub 네트워크에 게시합니다. 메시지 및 기타 생성된 이벤트를 수신하거나 듣고자 하는 사용자는 PubNub 네트워크에 가입하고 메시지를 파싱합니다. 이벤트 리스너는 PubNub 네트워크에서 생성된 메시지와 이벤트를 포착하고 발생한 동작에 따라 트리거하는 데 사용됩니다.
메시지가 올바른 수신자에게 전달되도록 하기 위해 채널은 데이터가 한 장치에서 다른 장치로 전송되는 메커니즘으로 사용됩니다. 채널은 디바이스가 PubNub 네트워크에 메시지를 게시하고 구독하고자 할 때마다 필요합니다. 사용자는 한 번에 하나의 메시지만 게시할 수 있지만, 한 번에 여러 개의 채널을 구독할 수 있습니다.
PubNub Unity SDK 설치 및 구성하기
시작하려면 PubNub 종속 요소를 설치하고 애플리케이션을 PubNub 네트워크에 연결하도록 PubNub Unity SDK를 구성해야 합니다. 이 가이드에서는 Unity 게임 엔진, Unity 에셋, Visual Studio와 같은 코드 에디터가 이미 설치되어 있다고 가정합니다. 자세한 내용은 Unity SDK 설명서를 참조하시기 바라며, 개략적인 내용은 다음과 같습니다:
- 패키지 관리자를 통해 Unity 패키지를 추가합니다.
- 무료 PubNub 계정을 생성하고 PubNub 키를 받습니다. 키 세트에서 애플리케이션에 필요한 기능을 활성화해야 합니다. 이 가이드에서는 기본 설정으로 스트림 컨트롤러를 활성화해야 합니다. 다른 중요한 기능인 함수는 이 가이드의 뒷부분에서 설명하는 함수를 초기화하면 자동으로 활성화됩니다.
- 새 Unity 프로젝트를 생성하거나 기존 게임을 열고 이전 단계에서 얻은 퍼블리시 및 구독 키를 Unity에 제공하여 Unity 에디터에서 PubNub 게임 오브젝트를 구성합니다. 또한 모든 PubNub 오브젝트에 고유 식별자가 있어야 PubNub에 연결할 수 있으므로 UserId를 제공해야 합니다. 이 작업을 완료했으면 PubNub 오브젝트를 초기화합니다:
using PubnubApi;
using PubnubApi.Unity;
…
PubNub pubnub = new Pubnub(pnConfiguration);
- 게임이 메시지에 반응하도록 이벤트 리스너를 추가하면 백엔드에서 기본적으로 새 메시지가 수신될 때 알림을 받게 됩니다. 각 유형의 메시지나 이벤트에 응답하는 사용자 지정 로직을 구현할 수 있는 다양한 이벤트 리스너가 있지만, 이 가이드에서는 메시지 이벤트 리스너만 있으면 됩니다:
var listener = new SubscribeCallbackListener();
pubnub.AddListener(listener);
listener.onMessage += OnPnMessage;
…
private void OnPnMessage(Pubnub pn, PNMessageResult<object> result) {
Debug.Log($"Message received: {result.Message}");
//Handle the message based on channel name, User ID, etc.
}
경기 중 중요한 정보: 스코어보드
스코어보드 또는 점수 시스템은 게임에서 게임 중 플레이어에게 피드백을 제공하는 방법으로 사용됩니다. 점수판은 가치 있고 매력적이며 보람 있는 피드백을 제공하여 즐거운 경험과 재플레이를 유도하여 점수를 향상시키는 데 필수적입니다. Unity 프로젝트에 구현할 수 있는 다양한 점수판 유형에 대한 점수 시스템 가이드를 확인하세요.
경기 중 점수판을 업데이트하는 것은 기본적으로 채팅 메시지를 보내는 것과 동일하지만 훨씬 더 빠른 속도로 이루어집니다. 필요한 정보로 구성된 페이로드를 구성하고 이 메시지를 게시하면 모든 구독자가 새로운 정보가 발생할 때마다 점수판을 수신, 파싱, 업데이트할 수 있습니다. 멀티플레이어 동기화와 같은 다른 멀티플레이어 기능을 지원하는 데 PubNub을 사용하는 경우, 전송해야 하는 메시지 수가 방대해지므로 이 정보를 함께 묶어 전송하는 것이 좋습니다. 하지만 이 가이드에서는 메시지를 보내고 받는 데 필요한 PubNub 기능에만 초점을 맞추겠습니다.
스코어보드 구현을 시작하려면, 경기에 참여한 사람들만 업데이트를 받도록 채널 패턴을 설정하세요. 멀티플레이어 동기화를 위한 아키텍처에 따라 현재 매치를 플레이어와 고유하게 식별하는 일종의 방 ID 또는 매치 ID가 있어야 합니다. 채널을 구성할 때 이 ID를 사용하세요:
public string scoreboardUpdates = $“scoreboard.” + {RoomID};
채널은 문자열 보간을 사용하여 점수판 채널과 현재 매치의 식별자를 결합합니다. 이 채널을 구독하면 채널 업데이트를 수신할 수 있습니다:
pubnub.Subscribe<string>()
.Channels(new string[] {
// subscribe to channels
scoreboardUpdates
})
.Execute();
킬을 달성하거나 피해 점수가 증가하는 등의 업데이트가 있으면 메시지를 구성하여 업데이트를 게시합니다(단순한 스코어보드 업데이트보다 더 많은 정보를 보내고 싶을 경우):
Dictionary<string, object> leaderboardUpdates= new Dictionary<string, object>();
leaderboardUpdates.Add("userId", user-a-uuid);
leaderboardUpdates.Add("kills", 0);
leaderboardUpdates.Add("deaths", 0);
leaderboardUpdates.Add("assists", 0);
leaderboardUpdates.Add("total_damage", 0);
…
private async void PublishMessage(string text, string channel)
{
await PNManager.pubnubInstance.pubnub.Publish()
.Channel(scoreboardUpdates)
.Message(text)
.ExecuteAsync();
}
다른 플레이어는 앞서 구성한 메시지 이벤트 리스너를 통해 새로운 업데이트를 수신하게 됩니다. 그런 다음 메시지를 파싱하고 그에 따라 UI를 업데이트하면 됩니다. 이 작업은 게임이 종료될 때까지 계속되며, 이 경우 글로벌 순위표를 업데이트하기 위해 마지막으로 한 번만 호출합니다.
최고 점수 순위: 리더보드
순위표는 게임에서 플레이어 간의 경쟁을 유도하는 데 매우 중요하며, 경기가 끝난 후 또는 홈 화면의 별도 메뉴에 표시됩니다. 플레이어는 다른 플레이어, 길드, 클랜과 비교하여 자신의 성적을 확인하고 더 높은 점수를 얻기 위해 어떻게 플레이 스타일을 개선할 수 있는지 알 수 있기를 원합니다. Unity 게임에서 구현할 수 있는 다양한 유형의 리더보드에 대해 자세히 알아보려면 리더보드 가이드를 확인하세요.
온라인 순위표 구현을 시작하기 전에, 경기가 끝난 후 순위표를 업데이트할 뿐만 아니라 서버를 가동하지 않고도 순위표 정보를 저장할 수 있는 방법에 대해 알아볼 필요가 있습니다.
함수를 사용하면 개발자가 엣지에서 비즈니스 로직을 생성하고 실행하여 PubNub 네트워크를 통해 실시간 메시지를 라우팅, 필터링, 변환, 증강 및 집계할 수 있습니다. 서버를 가동할 필요 없이 이 비즈니스 로직을 호스팅할 수 있으며, 신뢰할 수 있는 타사 통합 (이미 함수와 함께 작동하도록 설정되어 있고 시작 지침이 포함되어 있음)과 통합하거나 코드를 작성하여 플레이어에게 보내기 전 또는 후에 사용자 지정 로직을 수행할 수 있습니다. 함수의 데이터베이스 역할을 하는 영구 키 값 저장소인 KV 저장소 모듈을 사용하여 관련 정보를 저장할 수도 있습니다. 함수에 대한 자세한 내용은 문서를 참조하세요.
순위표의 경우 플레이어가 경기를 마친 후 점수를 업데이트한 다음 업데이트된 순위표를 플레이어에게 알리고 싶을 수 있습니다.
함수를 사용하려면 관리자 포털에서 몇 가지 설정을 더 수행해야 합니다:
- 관리자 포털로 이동합니다.
- 포털 왼쪽에 있는 기능 탭을 클릭합니다.
- 이전 섹션에서 만든 앱과 키 집합을 선택합니다.
- 새 모듈 만들기를 클릭합니다.
- 모듈에 이름을 지정합니다.
- 모듈이 수행하는 작업에 대한 설명을 입력합니다.
- 앞서 만든 키 집합을 선택하여 모듈을 추가합니다. 만들기를 클릭합니다.
- 함수 이름을 지정합니다.
- 게시 후 또는 실행 후 이벤트 유형을 선택합니다.
- 메시지가 게시된 후 함수가 업데이트할 채널 이름을 입력합니다(이 이름도 나중에 조정할 수 있음). 와일드카드 구독 문자 * 기능으로 구성된 score.*와 같은 채널 이름을 사용하게 됩니다. 다음 가이드에서 채팅 메시지에서 와일드카드 구독이 어떻게 작동하는지에 대해 자세히 알아볼 수 있습니다.
- 각 함수에 대해 만들기 버튼을 클릭합니다.
함수 개요 페이지로 이동하여 설정을 변경하고, 테스트하고, 각 함수가 게임과 상호작용할 때 모니터링할 수도 있습니다. 화면 중앙에 자동으로 생성된 자바스크립트 코드가 있을 것입니다. 이것은 함수의 작동 방식과 코드를 호스팅하거나 타사 통합의 비즈니스 로직을 실행할 수 있는 예시를 보여주기 위한 샘플 "Hello World" 함수입니다.
리더보드의 경우 몇 가지 사용자 정의 로직을 작성하고 KV 스토어 모듈을 사용하여 리더보드 정보를 저장합니다. 코드 섹션에서 리더보드 정보에 포함할 내용을 고려해야 합니다. 서로 다른 정보를 자세히 설명하는 여러 개의 리더보드, 여러 통계를 포함하는 큰 리더보드, 게임에서 다양한 리더보드를 만들 수 있는 리더보드를 만들 것인가요?
저장할 정보를 결정한 후에는 게임에서 PubNub 네트워크에 게시한 다음 함수에 의해 포착될 메시지 페이로드를 설정해야 합니다.
예를 들어, 유니티 쇼케이스 게임에서는 경기가 끝나면 경기에 참여한 각 플레이어의 이름과 킬/데스/어시스트의 조합인 점수를 전송합니다. 메시지는 JSON 형식으로 형식화되어 함수가 수신 중인 채널 score.leaderboard에 게시됩니다 (와일드카드 구독에 기반). UIManager.cs 파일을 구체적으로 살펴보세요:
…
// Get the kills and deaths value of all players and store them in an INT array:
int[] kills = new int[playersSorted.Length];
int[] deaths = new int[playersSorted.Length];
int[] otherScore = new int[playersSorted.Length];
for (int i = 0; i < playersSorted.Length; i++)
{
kills[i] = playersSorted[i].Kills;
deaths[i] = playersSorted[i].Deaths;
otherScore[i] = playersSorted[i].OtherScore;
if (notPublished)
{
if (playersSorted[i].PlayerName == Connector.PNNickName)
{
MyClass mc = new MyClass();
mc.username = Connector.PNNickName;
mc.score = playersSorted[i].Kills.ToString();
string json = JsonUtility.ToJson(mc);
PublishMessage(json, _leaderboardChannelPub);
}
notPublished = false;
}
}
…
private async void PublishMessage(string text, string channel)
{
await PNManager.pubnubInstance.pubnub.Publish()
.Channel(channel)
.Message(text)
.ExecuteAsync();
}
그러면 이 채널에서 수신 대기 중인 함수가 트리거되고 KV 스토어 모듈에서 새 점수를 정렬하고 업데이트하며 새 리더보드 업데이트의 플레이어를 업데이트할 수 있습니다. Unity 쇼케이스 게임의 경우 함수의 다음 로직이 정확히 이 작업을 수행합니다:
//This function takes a string from a unity game that contains either a username AND and a score, OR a refresh message.
//The function then looks at the message and creates a user/score json and sends it back. Putting the highest score in 0 and the lowest score in [9]
//If the score submitted is lower than [9] then trhe messages succeeds without intervention
//sending a refresh will trigger this function without any intervention.
export default (request) => {
const db = require("kvstore");
const pubnub = require("pubnub");
//uncomment if you want to see the raw message
//console.log(request.message);
//The format of the message sent is "{\"username\":\"Bob\",\"score\":\"10\",\"refresh\":\"\"}" and as such we need to parse it
//You wont be able to use the test payload until you remove the parse
// var json = request.message; //uncomment this and comment the line below to be able to use the test payload (as well as debug console)
var json = JSON.parse(request.message);
let { username, score } = json;
//create some arrays to ultimately be able to position the leaderboard correctly - there's more elegant ways to do this, this function is designed to explain
var scorearrayprevious = [];
var scorearraynew = [];
var usernamearraynew = [];
var usernamearrayprevious = [];
//db.removeItem("data"); //uncomment this code if you need to wipe the database -- for future you could always send a message to trigger this, but that is out of the scope for this workshop
db.get("data").then((value) => {
if(value){
console.log("value", value); //uncomment this if you want to see the value
let i = 0;
//we use some and score > item to parse through where the submitted score will sit, if the score is greater than the item we're on, then it get's slotted in to the array at that spot
value.score.some(item => {
if(parseFloat(score) > parseFloat(item) || (parseFloat(item) == 0 && score.length > 0)){ //Parse into float since variables are currently strings
//Score
scorearraynew = value.score.slice(0, i);
scorearrayprevious = value.score.slice(i, value.score.length);
console.log("values", scorearraynew, scorearrayprevious);
scorearraynew.push(score);
var newScoreList = scorearraynew.concat(scorearrayprevious);
newScoreList.splice(-1,1);
//Username
usernamearrayprevious = value.username.slice(0, i);
usernamearraynew = value.username.slice(i, value.score.length);
console.log("values", usernamearrayprevious, usernamearraynew);
usernamearrayprevious.push(username);
var newUsername = usernamearrayprevious.concat(usernamearraynew);
newUsername.splice(-1,1);
value.score = newScoreList;
value.username = newUsername;
//store the
db.set("data", value);
return true; //break out of the loop using Array.prototype.some by returning true
}
i++;
});
//publish the message to a *new* or *different* channel
pubnub.publish({
"channel": "leaderboard_scores",
"message": value
}).then((publishResponse) => {
console.log("publish response", publishResponse);
});
} else {
//Initial Data, used only on the first call
db.set("data", {
"username":["---","---","---","---","---","---","---","---","---","---"],
"score":["0","0","0","0","0","0","0","0","0","0"]});
}
});
return request.ok();
};
그런 다음 함수는 leaderboard_scores 채널을 통해 모든 플레이어에게 리더보드 업데이트를 게시합니다. 애플리케이션으로 돌아가서 구독 호출을 통해 이 채널을 구독해야 합니다:
pubnub.Subscribe<string>()
.Channels(new string[] {
// subscribe to channels
"leaderboard_scores”
})
.Execute();
리더보드_스코어
채널을 구독하고 있으므로 메시지 이벤트 리스너를 통해 함수가 완료되면 업데이트된 리더보드 점수를 수신할 수 있습니다. 그런 다음 메시지를 파싱하고 그에 따라 리더보드 UI를 업데이트할 수 있습니다. 예를 들어 Unity 쇼케이스 게임 UI 리더보드를 업데이트할 수 있습니다:
private void OnPnMessage(PNMessageResult<object> result)
{
// Enable the button once we have established connection to PubNub
if (result.Channel.Equals(PubNubUtilities.chanLeaderboardSub))
{
Dictionary<string, object> msg = JsonConvert.DeserializeObject<Dictionary<string, object>>(result.Message.ToString());// as Dictionary<string, object>;
var usernames = (msg["username"] as Newtonsoft.Json.Linq.JArray).ToObject<string[]>();
var scores = (msg["score"] as Newtonsoft.Json.Linq.JArray).ToObject<string[]>();
if (usernames[0] != null)
{
namePos1.text = usernames[0];
kdPos1.text = scores[0];
}
if (usernames[1] != null)
{
namePos2.text = usernames[1];
kdPos2.text = scores[1];
}
if (usernames[2] != null)
{
namePos3.text = usernames[2];
kdPos3.text = scores[2];
}
if (usernames[3] != null)
{
namePos4.text = usernames[3];
kdPos4.text = scores[3];
}
if (usernames[4] != null)
{
namePos5.text = usernames[4];
kdPos5.text = scores[4];
}
}
}
Unity 쇼케이스 게임의 리더보드 구현에 대한 자세한 내용은 Leaderboard.cs 파일을 참조하세요.
다음 단계
이 사용법 가이드에서는 Unity 게임에 리더보드와 스코어보드를 추가하는 방법을 배웠습니다. 스코어보드를 추가하려면 PubNub의 저지연 플랫폼을 사용하여 킬, 사망, 어시스트 등 경기 중 관련 정보가 포함된 메시지를 주고받으며 플레이어를 실시간으로 업데이트할 수 있습니다. 순위표의 경우, 함수는 플레이어 점수를 업데이트하는 코드를 호스팅하고 경기가 끝난 후 플레이어가 볼 수 있도록 순위표를 업데이트할 수 있습니다.
게임 개발자는 다음 리소스를 통해 자세히 알아볼 수 있습니다:
- 문서를 읽어보세요.
- Unity에서 실시간 채팅을 추가하는 방법을 알아보세요.
- 유니티 쇼케이스 게임에서 실시간으로 스코어보드와 리더보드를 구현하는 방법을 알아보세요.
- Unity SDK 소스 코드를 살펴보세요.
궁금한 점이 있으면 언제든지 개발자 지원팀( devrel@pubnub.com )으로 문의하세요.
펍넙은 어떤 도움을 드릴 수 있나요?
이 문서는 원래 PubNub.com에 게시되었습니다.
저희 플랫폼은 개발자가 웹 앱, 모바일 앱 및 IoT 디바이스를 위한 실시간 상호작용을 구축, 제공 및 관리할 수 있도록 지원합니다.
저희 플랫폼의 기반은 업계에서 가장 크고 확장성이 뛰어난 실시간 에지 메시징 네트워크입니다. 전 세계 15개 이상의 PoP가 월간 8억 명의 활성 사용자를 지원하고 99.999%의 안정성을 제공하므로 중단, 동시 접속자 수 제한 또는 트래픽 폭증으로 인한 지연 문제를 걱정할 필요가 없습니다.
PubNub 체험하기
라이브 투어를 통해 5분 이내에 모든 PubNub 기반 앱의 필수 개념을 이해하세요.
설정하기
PubNub 계정에 가입하여 PubNub 키에 무료로 즉시 액세스하세요.
시작하기
사용 사례나 SDK에 관계없이 PubNub 문서를 통해 바로 시작하고 실행할 수 있습니다.
Posted on May 15, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 29, 2024