리더보드 관련 문의입니다.

고객님의 문의에 답변하는 직원은 고객 여러분의 가족 중 한 사람일 수 있습니다.
고객의 언어폭력(비하, 조롱, 욕설, 협박, 성희롱 등)으로부터 직원을 보호하기 위해
관련 법에 따라 수사기관에 필요한 조치를 요구할 수 있으며, 형법에 의해 처벌 대상이 될 수 있습니다.

커뮤니티 이용 정책에 위배되는 게시물을 작성할 경우, 별도 안내 없이 게시물 삭제 또는 커뮤니티 이용이 제한될 수 있습니다.

문의 응대 : 평일 오전 10시 ~ 오후 6시
문의를 남기실 경우 다음 항목을 작성해 주세요.
정보가 부족하거나 응대시간 외 문의하는 경우 확인 및 답변이 지연될 수 있습니다.

  • 뒤끝 SDK 버전 :
  • 프로젝트명 :
  • 스테이터스 코드 :
  • 에러 코드 :
  • 에러 메시지 :

리더보드로 랭킹시스템을 개발하고있는데 2가지 문의가 있습니다.

  1. 유저가 리더보드에 랭킹등록을할때마다 비용이 청구되는건지
    만약 리더보드에 새로 요청이들어갈때마다 청구되는거라면 얼마의 비용이 청구되는지 궁금합니다.

  2. 동일한 점수의 유저가 리더보드에 등록되어있을때 순위를 어떻게 표기되는것인지 어떤유저가 더높은 순위에 있는지도 궁금합니다.

안녕하세요 개발자님,
뒤끝의 베이스 기능들은 호출에 따른 종량형 요금제로 제공중에 있습니다.
리더보드와 관련한 기능은 1회 호출 기준 0.04원의 비용이 발생합니다.
동순위 유저의 경우 순위는 동일하게 제공되며 UUID 순으로 제공됩니다.

그러면 순위별 보상을주는부분에서 동일한 점수의 1등이 5명이라면 그다음등수는 6등으로나오고 5명은 1등의 보상을 수령하게 되나요?

네 맞습니다.
1등이 5명이라면 5명에게 1등 보상이 주어지고, 다음 순위 유저는 6등으로 처리됩니다.

그러면 동일한 점수라고 했을때 먼저 등록된 시간순으로 등수를 나누고 싶으면 어떻게 해야할까요?

현재 정렬 기능과 관련해서는 별도의 기능을 제공하지 않고 있습니다.
필요 시 추가항목에 랭킹 갱신 시간 등의 정보를 넣어서,
해당 정보를 기준으로 클라이언트에서 재구성하는 방법으로 가능할 것 같습니다.

확인해보니까
owner_inDate, client_date이 2가지 데이터는 등록가능하고
updatedAt데이터를 넣는 부분은없는 것 같은데
테이블에 updateAt 을 추가로 만들어서 그시간을 받아서 재구성해야한다는 말씀이신가요?

리더보드 생성 시 스코어 필드 외에 추가적인 데이터를 활용할 수 있도록 추가항목(extra data)를 설정하여 구성할 수 있도록 제공중에 있습니다.

추가항목을 사용하면 별도의 추가 조회없이 리더보드 순위 조회시 추가항목 데이터가 함께 재공됩니다.

안내해주신 가이드라인보고 개발하고있는데
리더보드에 추가필드를 제작해서 호출해야된다는 말인건가요? 그냥

 public void UpdateLeaderboardStage(int newStage)
    {
        const string tableName = "UserStageData";
        string leaderboardUuid = StageRankUUID;

        string rowIndate = InDateManager.Get(tableName);
        if (string.IsNullOrEmpty(rowIndate))
        {
            Debug.LogError("[Rank] inDate 없음");
            return;
        }

        // 내 랭킹 조회 (성공/실패와 무관하게 처리 계속 진행)
        var myRankBro = Backend.Leaderboard.User.GetMyLeaderboard(leaderboardUuid);

        int oldScore = 0;
        bool isRegistered = false;

        // 조회 성공 + 등록된 데이터가 있는 경우만 oldScore 세팅
        if (myRankBro.IsSuccess())
        {
            var myRankList = myRankBro.GetUserLeaderboardList();
            if (myRankList != null && myRankList.Count > 0)
            {
                oldScore = int.Parse(myRankList[0].score);
                isRegistered = true;
            }
        }
        else if (myRankBro.GetStatusCode() == "404")
        {
            string msg = myRankBro.GetMessage();

            if (msg.Contains("userRank not found"))
            {   
                //랭킹 등록 안된상태라면 
                isRegistered = false;
            }
            else if (msg.Contains("leaderboard not found"))
            {
                // 리더보드 UUID 잘못됨
                Debug.LogError($"[Rank] 잘못된 UUID: {myRankBro}");
                return;
            }
        }
        else
        {
            Debug.LogError($"[Rank] 내 랭킹 조회 실패: {myRankBro}");
            return;
        }
        // else: 실패했거나 등록이 아예 없는 경우 → 신규 등록으로 간주


        // 랭킹 등록 안 됐거나, 점수가 더 크면 업로드
        if (!isRegistered || newStage > oldScore)
        {
            var param = new Param();
            param.Add("HighStageIndex", newStage);
            param.Add("extraData", DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString());

            var bro = Backend.Leaderboard.User.UpdateMyDataAndRefreshLeaderboard(leaderboardUuid, "UserStageData", rowIndate, param);
            Debug.Log(bro);
            if (bro.IsSuccess())
            {
                Debug.Log(isRegistered
                    ? $"[Rank] 기록 갱신 성공: {oldScore} → {newStage} {param}"
                    : $"[Rank] 신규 등록 성공: {newStage}");
            }
            else
            {
                Debug.LogError($"[Rank] 리더보드 업로드 실패: {bro}");
            }
        }
        else
        {
            Debug.Log($"[Rank] 기존 기록({oldScore}) >= 새 기록({newStage}), 업로드 생략");
        }
    }

 public void PrintTop100Leaderboard()
    {
        string leaderboardUuid = StageRankUUID; // 실제 UUID 넣으세요

        // 1 ~ 50위
        var bro1 = Backend.Leaderboard.User.GetLeaderboard(leaderboardUuid, 50, 0);
        if (bro1.IsSuccess())
        {
            var list = bro1.GetUserLeaderboardList();

            foreach (var item in bro1.GetUserLeaderboardList())
            {
                Debug.Log($"{item.rank}위 ({item.score}) : {item.nickname}, 등록시간={item.extraData}");
            }
        }
        else
        {
            Debug.LogError($"[Rank] 1~50위 조회 실패: {bro1}");
        }
    }

이렇게해서 호출하니까 item.extraData값이 비어있던데 가이드라인하고 무슨차인지 모르겠습니다.

그리고 또하나 리더보드에서 순위 삭제시 삭제안되는 문제가 너무자주발생합니다.

다른분들 글보면 답변으로는 삭제된건데 캐시가 남아서 보이는거다 라고 적혀잇는데 삭제가된거면

유니티에서 호출 했을때 해당 랭킹들은 호출이안되야하는거아닌가요? 삭제 시도한 데이터들도 모두 정상적으로 호출이됩니다.

리더보드가 안정화가 제대로 이뤄진게맞는걸까요?

보유하신 리더보드의 프로젝트 상에는 추가항목이 활성화된 리더보드가 확인되지 않습니다.
앞서 안내드린것과 같이 리더보드 생성시에만 추가항목 설정이 가능하기에,
추가 항목이 설정되지 않았따면 정보를 넣어 갱신을 시도하더라도, 실제 리더보드 순위정보에는 해당 정보가 등록되지 않습니다.
리더보드 설정상 생성 당시 추가항목을 설정하지 않았다면 리더보드 갱신 및 조회 시 item.extraData 값은 제공되지 않기에 새로운 리더보드를 생성하여 확인해 주시기 바랍니다.

생성 당시 추가항목을 설정하는 경우 아래 이미지와 같이 확인됩니다.

순위 정보 미삭제 현상과 관련해서는 영업시간중 상세 확인하여 안내드리겠습니다.
이용에 불편드려 죄송합니다.

아~그럼 이전에 문의드린것처럼 테이블에 추가필드부분을 추가한다음에 저장해야되는게 맞군요…

하나만 더 문의하겠습니다~

지금 보상이 우편으로 자동 발송되는것만 있는것 같은데 바로 이전 랭킹확정난 보상으로 유저가 직접 수령하게 하고싶으면

GetLeaderboardReward 이걸 사용해서해야하나요?
GetPastLeaderboard이걸 사용해서해야하나요?
우편발송이아닌 유저가 버튼을 눌러 직접수령하게 제작하고 싶습니다.

(제가 어제 일일 리더보드 제작하고 랭킹을 등록해놨는데 과거 기록이 전혀 남지않아서 문의드리는겁니다)

확인 시 해당 리더보드의 과거 이력이 존재하지 않는 것은 보상 이력이 존재하지 않기 때문입니다.
과거이력은 정산과 함께 보상 이력을 기반으로 제공되나, 해당 리더보드는 보상 정보가 등록되지 않아 보상이 발송되지 않았습니다.

리더보드 보상이 우편으로 제공되기는 하나,
단순 우편조회가 아닌 rank 파라미터의 우편조회 및 우편 수령 함수를 통해서만 수령할 수 있기에,
UI상 관련 함수들로 구성을 해주시면 기획한 바와 동일하게 처리가 가능할 것으로 확인됩니다.

어제 문의해주신 리더보드 순위 삭제 불가 현상과 관련해서는 확인중에 있습니다.
확인이 완료되는대로 안내드리겠습니다.

아 그럼 직접 수령을 할 생각이 있더라도 보상테이블에 보상목록을 세팅해야한다는 말씀이신거죠?

그리고 보상 수령우편도 코드로 세팅해놔야 발송이된다는 말씀이신가요?

그래서 그 발송을 수령버튼처럼만들고 처리하면된다는걸로 이해했습니다.

네 맞습니다.
보상우편으로 발송되더라도 코드 구성을 자동으로 수령하게 하지 않는 한
UI 구성을 통해 유저가 직접 수령하는 형태로 제공하는 것이 일반적입니다.

리더보드 보상 발송은 리더보드 설정상 보상 정보가 설정이 이루어져야 발송이 이루어지며,
발송 이력이 존재해야 과거 이력으로써 확인이 가능해집니다.

수령을 위해서는 아래와 같이 Rank 타입으로 우편 조회 및 수령을 하는 코드가 구성되어야 합니다.
Backend.UPost.GetPostList(PostType.Rank, 10);
Backend.UPost.ReceivePostItemAll(PostType.Rank);

좋아요 1

콘솔 내 리더보드 순위 정보가 삭제되지 않는 현상은 원인을 확인하여 수정이 완료되었습니다.
콘솔 내에서 정상 삭제가 가능하니 참고하여 이용해 주시면 감사하겠습니다.
불편드려 죄송합니다.

좋아요 1

안내해주신 것처럼 extra 설정을 통해 랭킹 표시까지는 구현했는데, 보상 지급 단계에서 문제가발생 하고 있습니다.
보상은 과거 기록의 랭킹을 기준으로 지급되는데, 과거 기록에는 랭킹과 스코어만 저장되고 extra 데이터는 포함되지 않아 등수 구분이 불가능합니다.
따라서 1등이 3명일 경우, 모두 1등 보상을 받게 되는데요.
표기만 extra데이터로 1,2,3등으로 될 뿐 보상은 1등보상 3명을 받게 되는 구조가 만들어져서
extra데이터 등수 표기가 의미가 없어져버립니다.
방법이 있나요?

보상 우편을 통해서 보상을 지급하도록 구현하신 것이 아니라,
자체 보상을 구현하고 계신걸까요?

동순위 보상을 지급하지 않고 자체 보상을 지급하시고자 한다면 뒤끝의 리더보드 기능으로는 구현이 불가합니다.
다른 방향으로 자체적으로 구성해주셔야 합니다.

과거 랭킹을 기준으로
GetLeaderboardRewardList에서 보상목록을 받아와 보상을 주는 식으로 구현중에있습니다.
결국 뒤끝 리더보드를 이용해서 랭킹을 구현하게되면 동순위 보상으로밖에 제작할 수 없다 라고 이해하면될까요?

이렇게된다면 랭킹1위가 5명이면 조회할때마다 5명의 순서가 매번 변경될까요? 아니면 어떤순서로정렬되는 구조인가요?
제작중인 랭킹에서 1,2,3위의 캐릭터를 보여주는 부분이있어서 유저입장에서 민감하게 받아들일까봐 자꾸질문하게됩니다.ㅠㅠ

네, 맞습니다.
뒤끝 리더보드를 통해서는 동점자에 대해서는 개별순위 보상을 지급할 수 없습니다.

말씀하신 형태의 리더보드 및 보상을 구현하고자 한다면 온전히 score 정보를 통해서 개별순위가 구성되도록 구현해주시는 방법 뿐입니다.

동순위 정렬은 UUID 순으로 제공되고 있습니다.

좋아요 1