[패스트캠퍼스 수강 후기] 올인원 패키지 : 유니티 포트폴리오 완성 100% 환급 챌린지 26회차 미션 시작합니다.

03. Firebase 네트워크 - 04-3, 05-1 챕터를 진행합니다.



저번 시간에 이어 LeaderboardController를 구현합니다.
금번 교육 내용만 작성하였습니다.




핵심은 score를 기준으로 데이터를 가져와서 정렬하여 처리하는 것입니다.

public class LeaderboardController : MonoBehaviour
{
    // 기존코드들..
    
    private bool sendUpdatedLeaderboardEvent = false;
    private event EventHandler<LeaderboardArgs> OnUpdatedLeaderboard;
    
    void Update() {
        // 기존 코드들..
        
        if (sendRetrievedScoreEvent) {
            sendRetrievedScoreEvent = false;
            OnRetrievedScore(this, retrievedScoreArgs);
        }
        
        if (sendUpdatedLeaderboardEvent) {
            sendUpdatedLeaderboardEvent = false;
            OnUpdatedLeaderboard(this, new LeaderboardArgs {
                scores = topScores,
                startDate = -1,
                endDate = -1
            });
        }
    }
    
    private bool gettingUserScore = false;
    public int GetUserScore(string userId) {
        gettingUserScore = true;
        databaseRef.Child(AllScoreDataPath) // 해당 Path에서
            .OrderByChild(UserScore.userIdPath) // Id Path 기준
            .StartAt(userId) // 시작부터
            .EndAt(userId) // 끝까지 취합
            .GetValueAsync().ContinueWith(task => {
                if (task.Exception !=) throw task.Exception;
                if (!task.IsCompleted) return;
                
                if (task.Result.Children == 0) {
                    retrievedScoreArgs = new UserScoreArgs(null, string.Format("No Scores for User {0}", userId);
                }
                else {
                    var scores = ParseValidUserScoreRecords(task.Result, -1, -1).ToList(); // 시간 내에 있는지
                    if (scores.Count == 0) {
                        retrievedScoreArgs = new UserScoreArgs(null, string.Format("No Scores for User {0} within time range {1} ~ {2}", userId, startDate, endDate);
                    }
                    else {
                        var orderedScored = scores.OrderBy(score => score.score);
                        var userScore = orderedScored.Last(); // 가장 큰값
                        retrievedScoreArgs = new UserScoreArgs(userScore, userScore.userId + " Retrieved!");
                    }
                }
                
                gettingUserScore = false;
                sendRetrievedScoreEvent = true; // Update에서 Event 발생.
            });
    }
    
    private List<UserScore> ParseValidUserScoreRecords(DataSnapShot snapshot, long startTicks, long endTicks) {
        return snapshot.Children
            .Select(scoreRecord => UserScore.CreateScoreFromRecord(scoreRecord))
            .Where(score => score != null && score.timestamp > startTicks && score.timestamp <= endTicks)
            .Reverse()
            .ToList();
    }
   
    
    private bool gettingTopScores = false;
    private void GetInitialTopScores() {
        gettingTopScores = true;
        var query = databaseRef.Child(AllScoreDataPath).OrderByChild("score");
        query = query.LimitToLast(20); // 20개
        query.GetValueAsync().ContinueWith(task => {
            if (task.Exception != null) { return; } // error
            if (!task.IsCompleted || !task.Result.HasChildren) return; // error
            
            var scores = ParseValidUserScoreRecords(task.Result, -1, -1);
            foreach (var userScore in scores) {
                if (!userScores.Contains(userScore.userId)) { // 기존값 존재하지 않는다면
                    userScores[userScore.userId] = userScore;
                }
                else { // 기존값 존재한다면
                    if (userScores[userScore.userId].score < userScore.score)
                        userScores[userScore.userId] = userScore; // score 갱신
                }
            }
            
            SetTopScores();
        });
    }
    
    private void SetTopScores() {
        topScores.Clear();
        topScores.AddRange(userScores.Values.OrderbyDecending(score => score.score));
        sendUpdatedLeaderboardEvent = true;
        gettingTopScores = false;
    }
}






Canvas에 "Leaderboard Handler"와 "Leaderboard UI Controller"를 Attach 시켰습니다.
플레이를 진행합니다.



화면과 같이 user_id, username, score를 입력하고 [Add] [Get User Score] [Update] 등의 버튼을 클릭하여, 사용자의 Score를 입력, 최대점수 얻기, Score 갱신 등을 테스트할 수 있습니다.

그리고 오른쪽의 [Get Leaderboard]를 클릭하면 최고점수의 user 부터 표시되는 것을 확인할 수 있습니다.

소스코드 예외 사항에 대한 처리는 동영상에는 없지만, 강의 자료에는 포함되어 있으므로 해당 소스를 보면 좀더 파악하기 좋을 것입니다.

여기까지 하여 기본적인 함수들을 이용하여 Leaderboard의 구현이 완료되었습니다.





이제 사용자의 데이터를 저장/불러오기 작업입니다.

firebase의 database 보안규칙

auth = 인증된 사용자 토큰.






권한 규칙을 설정할 수 있습니다.

"규칙 플레이그라운드"를 통해서 읽기/쓰기 권한에 대한 테스트를 해볼 수 있습니다.

인증이 된 경우에만 읽기/쓰기 작업이 되는 것 등을 확인할 수 있습니다.
또한 인증은 되었지만 다른 아이디로 테스트를 하는 경우에도 보안 규칙이 적용되어 에러가 발생하는 것 등을 확인할 수 있습니다.





위의 내용은 데이터 검증과 색인에 대한 내용입니다. 권한 규칙과 비슷해보이지만 다른 내용입니다. ㅎㅎ

.validate - 데이터가 올바른 형식인지 등
.indexOn - 개발상에서는 설정하지 않지만 Release시에는 규모가 커져도 정상 작동하도록 색인화를 하게됨. Database 용량이 많이 켜져도 쿼리 성능을 유지하기 위한 것이라고 보면 되겠습니다.




<위의 코드들은 제가 보면서 주요한 함수, 코드를 확인하기 위해 타이핑한 용도로, 전체 소스코드가 아님에 주의해 주세요. 전체 코드는 교육 수강을 하면 완벽하게 받으실 수가 있답니다 ^^>

패스트캠퍼스 - 올인원 패키지 : 유니티 포트폴리오 완성 bit.ly/2R561g0

 

유니티 게임 포트폴리오 완성 올인원 패키지 Online. | 패스트캠퍼스

게임 콘텐츠 프로그래머로 취업하고 싶다면, 포트폴리오 완성은 필수! '디아블로'와 '배틀그라운드' 게임을 따라 만들어 보며, 프로그래머 면접에 나오는 핵심 개념까지 모두 잡아 보세요!

www.fastcampus.co.kr

 

+ Recent posts