- 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 다음글이전글이전 글이 없습니다.댓글