• 티스토리 홈
  • 프로필사진
    개양반
  • 방명록
  • 공지사항
  • 태그
  • 블로그 관리
  • 글 작성
개양반
  • 프로필사진
    개양반
    • Everybody Happyvirus (87)
      • Unity DOTS (19)
        • ECS Sample Projtect (8)
        • Unity.Physics (1)
        • TIP (9)
      • Unity Assets 추천 (6)
        • BG Database (5)
        • I2 Localization - 현지화 (1)
      • Unity 자습서 (15)
        • Addressable (4)
        • 유니티 + 파이어베이스 (0)
        • GamingServices (10)
      • 주식 이야기 (4)
        • 회사 소개 (2)
        • 회사 정보 (1)
        • 실적 발표 (0)
      • 일상 생활 (9)
        • 도서리뷰 (2)
        • 제품리뷰 (6)
      • 게임일기 (2)
        • 리그오브레전드 (2)
      • 게임소개 (4)
      • 게임리뷰 (7)
  • 방문자 수
    • 전체:
    • 오늘:
    • 어제:
  • 최근 댓글
      등록된 댓글이 없습니다.
    • 최근 공지
        등록된 공지가 없습니다.
      # Home
      # 공지사항
      #
      # 태그
      # 검색결과
      # 방명록
      • Gamingservices - ABTestSample #5 재화 표시
        2023년 02월 26일
        • 개양반
        • 작성자
        • 2023.02.26.:37

        1. 오늘 알아볼 내용

        유저가 보유한 재화를 GamingServices에서 로드한 뒤에 UI에 표시하는 내용에 대해 다룹니다. 

        • 유저가 보유한 재화를 Economy 에서 로드하는 방법
        • 로드 중 발생한 에러를 처리하는 방법
        • Economy 에서 데이터를 로드한 후 UI에 표시하는 방법

         

         

        2. 유저가 보유한 재화 데이터 로드

        2-1 선행학습

        2-1-1 유저의 재화 데이터 로드 요청

        var options = new GetBalancesOptions { ItemsPerFetch = 100 };
        return EconomyService.Instance.PlayerBalances.GetBalancesAsync(options);
        GetBalancesOptions 한번에 로드할 목록의 수이다. 위 예제는 데이터를 로드할 때 100개씩 로드한다.
        기본 값은 20이며, 최대 100까지 입력할 수 있다.
        PlayerBalances 플레이어의 통화 잔액을 가져오고 업데이트하기 위한 모든 메서드가 포함되어 있다
        PlayerBalances.GetBalancesAsync(options) 유저가 보유한 재화들을 로드한다. 

         

        await getBalancesResult.GetNextAsync(options.ItemsPerFetch); 로 데이터를 추가로 더 로드할 수 있다.

        GetBalancesOptions options = new GetBalancesOptions
        {
            ItemsPerFetch = 5
        };
        
        GetBalancesResult getBalancesResult = await EconomyService.Instance.PlayerBalances.GetBalancesAsync(options);
        List<PlayerBalance> firstFiveBalances = getBalancesResult.Balances;
        
        
        if (getBalancesResult.HasNext) {
            // 추가로 로드하는 코드이다. GetNextAsync
            getBalancesResult = await getBalancesResult.GetNextAsync(options.ItemsPerFetch);
            List<PlayerBalance> nextFiveBalances = getBalancesResult.Balances;
        }

         

        2-2 스크립트 작업

        2-2-1 EconomyManager.cs

        Economy에게 유저가 보유한 재화를 로드하라고 요청하는 코드를 작성하겠습니다. EconomyManager 클래스에 아래의 전역변수와 함수를 추가합니다.

                // EconomyManager.cs
               
                public async Task RefreshCurrencyBalances()
                {
                    GetBalancesResult balanceResult = null;
                    balanceResult = await GetEconomyBalances();
        
                    if (this == null) return;
                }
            
                static Task<GetBalancesResult> GetEconomyBalances()
                {
                    var options = new GetBalancesOptions { ItemsPerFetch = 100 };
                    return EconomyService.Instance.PlayerBalances.GetBalancesAsync(options);
                }

         

        2-2-2 ABTestLevelDifficultySceneManager.cs

        유저가 로그인을 완료하면 GamingServices에게 데이터 로드를 요청하는 코드를 작성한다.

                // ABTestLevelDifficultySceneManager.cs
                
                async Task LoadDataFromServices()
                {
                    // -- 경제 구성요소 새로고침 관련 코드 생략
        
                    await LoadServicesData();
                    if (this == null) return;
        
                }
                
                // GamingServices로 부터 데이터 로드를 요청한다.
                async Task LoadServicesData()
                {
                    EconomyManager.instance.RefreshCurrencyBalances();
                }

         

         

        3. 로드한 데이터를 UI에 표시하기

        재화의 데이터를 표시하는 UI는 CurrencyItemView 클래스에서 관리하고 있다.

        각각의 CurrencyItemView 는 CurrencyHudView 클래스에서 관리하고 있다.

         

        3-1 스크립트 작성

        3-1-1 EconomyManager.cs

        EconomyManager 클래스에서 유저의 재화 데이터를 로드하면 CurrencyHudView 클래스에게 로드한 데이터를 UI에 표시하라고 요청하는 코드를 작성한다.

                // EconomyManager.cs
                
                // 전역 변수 추가
                public CurrencyHudView currencyHudView;
                
                public async Task RefreshCurrencyBalances()
                {
                    // -- 재화 데이터 로드 관련 코드 생략
        
                    // 데이터 로드가 완료되면 데이터를 UI에 표시한다.
                    currencyHudView.SetBalances(balanceResult);
                }

         

        3-2 테스트

        유니티로 돌아가 재생 버튼을 누르면 화면 상단에 Coin 개수가 표시되는 걸 확인할 수 있다.

         

         

        4. 데이터 로드 에러 처리

        서버로 부터 데이터를 로드하므로 클라이언트 외부의 문제로 에러가 발생할 수 있다. 예를 들면 네트워크 환경이 좋지 않거나 데이터 로드 횟수 초과 등을 꼽을 수 있다. 이러한 에러를 처리하는 방법에 대해 알아보자.

        참고로 에러 관련 코드는 깊게 분석하지 않았다. 프로젝트 만들때 그냥 복붙할 생각을 하고 있다. 유저가 어떤 이유로 에러가 생겼는지 알 수 있게 디버그로그 처리된 부분을 팝업창으로 변경할 생각하고 있다.

         

        4-1 스크립트 작성

        4-1-1 CancellationTokenHelper.cs

        Assets\Common\Scripts 폴더에 CancellationTokenHelper.cs를 만들고 아래의 코드를 작성한다.

        using System;
        using System.Threading;
        
        #if UNITY_EDITOR
        using UnityEditor;
        #endif
        
        namespace Unity.Services.Samples
        {
            // See Microsoft's CancellationTokenSource docs
            // (https://learn.microsoft.com/en-us/dotnet/api/system.threading.cancellationtokensource?view=net-6.0)
            // for more information about its purpose and functioning.
            public class CancellationTokenHelper : IDisposable
            {
                CancellationTokenSource m_CancellationTokenSource;
                bool m_Disposed;
        
                public CancellationToken cancellationToken => m_CancellationTokenSource.Token;
        
                public CancellationTokenHelper()
                {
                    m_CancellationTokenSource = new CancellationTokenSource();
        #if UNITY_EDITOR
                    EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
        #endif
                }
        
        #if UNITY_EDITOR
                void OnPlayModeStateChanged(PlayModeStateChange playModeStateChange)
                {
                    if (playModeStateChange == PlayModeStateChange.ExitingPlayMode)
                    {
                        m_CancellationTokenSource?.Cancel();
                    }
                }
        #endif
        
                // IDisposable related implementation modeled after
                // example code at https://learn.microsoft.com/en-us/dotnet/api/system.idisposable?view=net-6.0
                public void Dispose()
                {
                    Dispose(true);
                    GC.SuppressFinalize(this);
                }
        
                void Dispose(bool triggeredByUserCode)
                {
                    if (m_Disposed)
                    {
                        return;
                    }
        
                    // If triggeredByUserCode equals true, dispose both managed and unmanaged resources.
                    if (triggeredByUserCode)
                    {
                        // Dispose managed resources.
                        m_CancellationTokenSource.Dispose();
                        m_CancellationTokenSource = null;
                    }
        
        #if UNITY_EDITOR
                    // Clean up unmanaged resources.
                    EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
        #endif
        
                    m_Disposed = true;
                }
        
                ~CancellationTokenHelper()
                {
                    Dispose(false);
                }
            }
        }

         

        4-1-2 Utils.cs 

        Assets\Common\Scripts 폴더에 Utils.cs를 만들고 아래의 코드를 작성한다.

        using System;
        using System.Collections;
        using System.Collections.Generic;
        using System.Threading.Tasks;
        using UnityEngine;
        
        
        namespace Unity.Services.Samples
        {
            public static class Utils
            {
                public static async Task<T> RetryEconomyFunction<T>(Func<Task<T>> functionToRetry, int retryAfterSeconds)
                {
                    if (retryAfterSeconds > 60)
                    {
                        Debug.Log($"Economy returned a rate limit exception with an extended Retry After time " +
                                  $"of {retryAfterSeconds} seconds. Suggest manually retrying at a later time.");
                        return default;
                    }
        
                    Debug.Log($"Economy returned a rate limit exception. Retrying after {retryAfterSeconds} seconds");
        
                    try
                    {
                        // CancellationToken을 사용하면 지연 시간을 기다리는 동안 재생 모드를 종료하면
                        // Task.Delay가 취소되도록 할 수 있습니다.
                        // 그렇지 않으면 재생 모드 밖에서도 이 코드의 나머지 부분을 계속 실행하려고 시도할 것입니다.
                        using (var cancellationTokenHelper = new CancellationTokenHelper())
                        {
                            var cancellationToken = cancellationTokenHelper.cancellationToken;
        
                            await Task.Delay(retryAfterSeconds * 1000, cancellationToken);
        
                            // Call the function that we passed in to this method after the retry after time period has passed.
                            var result = await functionToRetry();
        
                            if (cancellationToken.IsCancellationRequested)
                            {
                                return default;
                            }
        
                            Debug.Log("Economy retry successfully completed");
        
                            return result;
                        }
                    }
                    catch (OperationCanceledException)
                    {
                        return default;
                    }
                    catch (Exception e)
                    {
                        Debug.LogException(e);
                    }
        
                    return default;
                }
            }
        }

         

        4-1-3 EconomyManager.cs 수정

        재화 데이터 로드를 요청하는 RefreshCurrencyBalances() 를 수정한다.

                // EconomyManager.cs
                
                public async Task RefreshCurrencyBalances()
                {
                    GetBalancesResult balanceResult = null;
        
                    try
                    {
                        balanceResult = await GetEconomyBalances();
                    }
                    catch (EconomyRateLimitedException e)
                    {
                        balanceResult = await Utils.RetryEconomyFunction(GetEconomyBalances, e.RetryAfter);
                    }
                    catch (Exception e)
                    {
                        // 아래의 코드를 팝업창에 띄워 유저가 어떤 에러가 발생했는지 알 수 있게 한다.
                        // 팝업창에 RefreshCurrencyBalances()를 요청하는 버튼을 만들어두는 것도 좋다.
                        Debug.Log("Problem getting Economy currency balances:");
                        Debug.LogException(e);
                    }
        
                    if (this == null) return;
        
                    // -- UI 표시 관련 코드 생략
                }

         

        5. 로그아웃과 함께 유저 재화 UI 정보 갱신

        로그아웃하면 현재 계정의 재화 금액이 UI에 표시되지 않드록 UI를 갱신해줘야 합니다.

        5-1 스크립트 작업

        5-1-1 EconomyManager.cs 수정

        아래의 함수를 EconomyManager.cs 에 추가합니다.

                // EconomyManager.cs
                
                public void ClearCurrencyBalances()
                {
                    currencyHudView.ClearBalances();
                }

         

        5-1-2 ABTestLevelDifficultySceneManager.cs 수정

        ABTestLevelDifficultySceneManager.SignOut 에서 로그아웃하면 위의 ClearCurrencyBalances를 호출하도록 함수를 수정합니다.

                // ABTestLevelDifficultySceneManager.cs
                
                void SignOut()
                {
                    if (AuthenticationService.Instance.IsSignedIn)
                    {               
                        EconomyManager.instance.ClearCurrencyBalances();
                        
                        // -- 계정 로그아웃 코드 관련 생략
                        // UpdateSceneViewAfterSignOut();
                    }
                }

        # 제가 깜빡하고 경제 데이터를 클리어한 뒤에 UI를 갱신하는 코드를 빼 먹었습니다. 관련 코드는 다음 게시글에 올리겠습니다. 

         

        오늘은 여기까지!

        제 블로그가 만족스럽다면 커피 한잔 값으로 후원을 해주실 수 있어요!

         

        저작자표시 비영리 변경금지 (새창열림)

        'Unity 자습서 > GamingServices' 카테고리의 다른 글

        Gamingservices - ABTestSample #7 Game Overrides 설정  (0) 2023.03.01
        Gamingservices - ABTestSample #6 Remote Key 만들기  (0) 2023.02.28
        Gamingservices - ABTestSample #4 재화 만들기  (0) 2023.02.25
        Gamingservices - ABTestSample #3 로그아웃과 신규 계정 생성  (0) 2023.02.25
        다음글
        다음 글이 없습니다.
        이전글
        이전 글이 없습니다.
        댓글
      조회된 결과가 없습니다.
      스킨 업데이트 안내
      현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
      ("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)
      목차
      표시할 목차가 없습니다.
        • 안녕하세요
        • 감사해요
        • 잘있어요

        티스토리툴바