Google Play Console 기본 설정
https://play.google.com/console
위 링크에서 25$를 지불하여 개발자 계정을 생성합니다.
개발자 계정 생성 후 우측 상단의 [앱 만들기] 버튼을 클릭하여 앱 세부 정보를 작성합니다.
[성장 > Play 게임즈 서비스 > 설정 및 관리 > 설정]을 선택하고 [아니요, 게임에서 Google API를 사용하지 않습니다]를 선택하여 Google Play Game Service를 생성합니다.
[Google Cloud Platform에서 OAuth 동의 화면 만들기]를 클릭합니다.
[Google Cloud Platform]를 클릭합니다.
User Type을 외부로 설정하고 [만들기] 버튼을 클릭합니다.
모든 필수 입력 사항을 작성하여 동의 화면을 게시합니다.
Google Play Console로 돌아와 [사용자 인증 정보 > 사용자 인증 정보 추가]를 선택합니다.
[게임 서버]를 선택하고 스크롤을 끝까지 내려 [인증 > OAuth 클라이언트 만들기]를 선택합니다.
위 양식에 맞는 OAuth 클라이언트를 만들어야 합니다.
다시 Google Cloud Platform으로 이동하여 [사용자 인증 정보 만들기]를 선택하고 [OAuth 클라이언트 ID]를 선택합니다.
[애플리케이션 유형]으로 웹 애플리케이션를 선택하고 [만들기] 버튼을 클릭합니다.
OAuth 클라이언트가 생성되었습니다.
다시 Google Play Console로 돌아와 [OAuth 클라이언트]를 선택하고 [변경사항 저장]을 클릭합니다.
게임 서버가 생성되었습니다.
Android 사용자 인증 정보 추가를 위해 [사용자 인증 정보 > 사용자 인증 정보 추가]를 선택하고 Android를 선택합니다.
스크롤을 끝까지 내려 [인증 > OAuth 클라이언트 만들기]를 선택합니다.
위와 같은 방법으로 OAuth 클라이언트를 만들어야 합니다.
위와 같이 작성 후 [만들기] 버튼을 누릅니다.
OAuth 클라이언트가 생성되었습니다.
위와 같이 생성된 것을 확인할 수 있습니다.
Package 설치하기
https://github.com/playgameservices/play-games-plugin-for-unity
위 링크에 접속하여 [current-build]를 선택합니다.
[GooglePlayGamesPlugin-0.10.14.unitypackage]를 선택합니다.
[Download] 버튼을 클릭하여 unitypackage 파일을 다운로드하고 실행합니다.
GooglePlayGamesPlugin을 Import할때 ExternalDependencyManager 폴더가 이미 존재하는 경우에는 체크를 해제한 후 Import합니다.
( 기존 폴더와 충돌을 일으킬 수 있습니다. )
Import가 완료되면 ExternalDependencyManager, GooglePlayGames, Plugins 폴더가 생성됩니다.
Unity 기본 설정
Google Play Console에 접속하여 [성장 >Play 게임즈 서비스 > 설정 및 관리 > 설정 > 사용자 인증 정보]를 선택하고 [리소스 보기]를 클릭합니다. 위 XML을 모두 복사합니다.
Unity로 돌아와 [Google Play Games > Setup > Android setup]을 선택합니다.
Resources Definition에 복사한 XML을 붙여 넣고 [Setup]을 클릭하여 Android Configure Setup을 완료합니다.
* 오류 메시지가 뜨는 경우 대부분 재실행시 해결됩니다.
[Assets > External Dependency Manager > Android Resolver > Force Resolve]를 선택하여 업데이트를 진행합니다.
* 오류 메세지가 뜨는 경우 Resolve후 Force Resolve를 선택합니다.
Force Resolve가 완료되었습니다.
Google Player Game Service - 업적, 리더보드, 이벤트, 클라우드 서비스 추가
Google Play Console로 이동하여 [성장 > Play 게임즈 서비스 > 업적]을 선택하고 [업적 만들기]를 클릭합니다.
다음과 같이 원하는 만큼 업적을 생성합니다.
이번에는 [이벤트]를 선택하고 [이벤트 만들기]를 클릭합니다.
다음과 같이 원하는 만큼 이벤트를 생성합니다.
이번에는 [리더보드]를 선택하고 [리더보드 생성]을 클릭합니다.
다음과 같이 원하는 만큼 리더보드를 생성합니다.
클라우드 서비스를 이용하기 위해서 [설정 > 속성 수정 > 저장된 게임]에서 사용을 선택합니다.
[Google Platform에서 보기]를 클릭합니다.
[라이브러리]를 선택합니다.
[검색어 입력창]에 Google Workspace Marketplace SDK를 입력하여 찾습니다.
[사용]을 눌러 해당 API를 사용합니다.
이제 클라우드 서비스 사용이 가능합니다.
Unity - 업적, 리더보드, 이벤트, 클라우드 서비스 추가
Google Play Console에 접속하여 [성장 >Play 게임즈 서비스 > 설정 및 관리 > 설정 > 사용자 인증 정보]를 선택하고 [리소스 보기]를 클릭합니다.
해당 XML을 모두 복사합니다.
Unity로 돌아와 [Google Play Games > Setup > Android setup]을 선택합니다.
Resources Definition에 복사한 XML을 붙여 넣고 [Setup]을 클릭하여 Android Configure Setup을 완료합니다.
Assets에 GPGSIds 파일이 생성되었습니다.
GPGSManager.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SocialPlatforms;
using GooglePlayGames;
using GooglePlayGames.BasicApi;
using GooglePlayGames.BasicApi.SavedGame;
using GooglePlayGames.BasicApi.Events;
public class GPGSManager
{
static GPGSManager instance = new GPGSManager();
public static GPGSManager Instance { get { return instance; } } // 싱글톤 구현
public bool IsAuthenticated { get { return Social.localUser.authenticated; } } // 로그인 여부를 확인합니다.
void Init() {
var config = new PlayGamesClientConfiguration.Builder()
.EnableSavedGames() // 클라우드 서비스를 이용하지 않는다면 이 줄을 지웁니다.
.Build();
PlayGamesPlatform.InitializeInstance(config);
PlayGamesPlatform.DebugLogEnabled = true;
PlayGamesPlatform.Activate();
}
public void Login(bool autoLogin = false, Action<bool, ILocalUser> callback = null) { // 로그인을 시도합니다.(autoLogin : 앱 실행시 자동로그인 => true / 사용자가 직접 로그인 => false)
Init();
PlayGamesPlatform.Instance.Authenticate(autoLogin ? SignInInteractivity.CanPromptOnce : SignInInteractivity.CanPromptAlways, (result) => {
callback?.Invoke(result == SignInStatus.Success, Social.localUser);
});
}
public void Logout() => PlayGamesPlatform.Instance.SignOut(); // 로그아웃합니다.
public void ShowAchievementsUI() => Social.ShowAchievementsUI(); // 모든 업적 목록을 표시합니다.
public void RevealAchievement(string gpgsID, float progress, Action<bool> callback = null) => Social.ReportProgress(gpgsID, progress, (bool success) => { callback?.Invoke(success); }); // 해당 업적을 진전시킵니다.
public void UnlockAchievement(string gpgsID, Action<bool> callback = null) => RevealAchievement(gpgsID, 100f, callback); // 해당 업적을 달성시킵니다.
public void ShowLeaderboardUI() => Social.ShowLeaderboardUI(); // 모든 리더보드 목록을 표시합니다.
public void ShowLeaderboardUI(string gpgsID) => PlayGamesPlatform.Instance.ShowLeaderboardUI(gpgsID); // 해당 리더보드를 표시합니다.
public void ReportLeaderboard(string gpgsID, long score, Action<bool> callback = null) => Social.ReportScore(score, gpgsID, (bool success) => { callback?.Invoke(success); }); // 리더보드에 점수를 기록합니다.
public void FetchEvent(string gpgsID, Action<bool, IEvent> callback = null) { // 해당 이벤트를 표시합니다.
PlayGamesPlatform.Instance.Events.FetchEvent(
DataSource.ReadCacheOrNetwork,
gpgsID,
(status, ievent) => {
if(status == ResponseStatus.Success) {
callback?.Invoke(true, ievent);
} else {
callback?.Invoke(false, null);
}
}
);
}
public void FetchAllEvents(Action<bool, List<IEvent>> callback = null) { // 이벤트 목록을 표시합니다.
PlayGamesPlatform.Instance.Events.FetchAllEvents(
DataSource.ReadCacheOrNetwork,
(status, ievents) => {
if(status == ResponseStatus.Success) {
callback?.Invoke(true, ievents);
} else {
callback?.Invoke(false, null);
}
}
);
}
public void IncrementEvent(string gpgsID, uint amount) => PlayGamesPlatform.Instance.Events.IncrementEvent(gpgsID, amount); // 해당 이벤트를 업데이트합니다.
public void SaveWithCloud(string filename, string serializedFile, Action<bool> callback = null) { // 클라우드 서비스를 이용하여 저장합니다.
ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;
savedGameClient.OpenWithAutomaticConflictResolution(
filename,
DataSource.ReadCacheOrNetwork,
ConflictResolutionStrategy.UseLastKnownGood,
(status, game) => {
if(status == SavedGameRequestStatus.Success) {
var updatedMetadata = new SavedGameMetadataUpdate.Builder().Build();
savedGameClient.CommitUpdate(
game,
updatedMetadata,
System.Text.Encoding.UTF8.GetBytes(serializedFile),
(ustatus, ugame) => {
callback?.Invoke(ustatus == SavedGameRequestStatus.Success);
}
);
} else {
callback?.Invoke(false);
}
}
);
}
public void LoadWithCloud(string filename, Action<bool, string> callback = null) { // 클라우드 서비스를 이용하여 로드합니다.
ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;
savedGameClient.OpenWithAutomaticConflictResolution(
filename,
DataSource.ReadCacheOrNetwork,
ConflictResolutionStrategy.UseLastKnownGood,
(status, game) => {
if(status == SavedGameRequestStatus.Success) {
savedGameClient.ReadBinaryData(game, (lstatus, lserializedFile) => {
if(lstatus == SavedGameRequestStatus.Success) {
string data_loaded = System.Text.Encoding.UTF8.GetString(lserializedFile);
callback?.Invoke(true, data_loaded);
} else {
callback?.Invoke(false, null);
}
}
);
} else {
callback?.Invoke(false, null);
}
}
);
}
public void DelectWithCloud(string filename, Action<bool> callback = null) { // 클라우드 서비스에 저장된 데이터를 삭제합니다.
ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;
savedGameClient.OpenWithAutomaticConflictResolution(
filename,
DataSource.ReadCacheOrNetwork,
ConflictResolutionStrategy.UseLongestPlaytime,
(status, game) => {
if(status == SavedGameRequestStatus.Success) {
savedGameClient.Delete(game);
callback?.Invoke(true);
} else {
callback?.Invoke(false);
}
}
);
}
}
위 스크립트를 원하는 곳에 저장하고 아래와 같은 방식으로 사용합니다.
로그인 · 로그아웃
if(GPGSManager.Instance.IsAuthenticated) { // 로그인 여부를 확인합니다.
// Google Play Game Service 로그인 상태
} else {
// Google Play Game Service 비로그인 상태
}
// GPGSManager.Instance.Login(bool autoLogin, Action<bool, ILocalUser> callback = null)
// autoLogin : false = 사용자 직접 로그인, true = 자동 로그인
GPGSManager.Instance.Login(false, (success, ilocalUser) => { // 로그인을 시도합니다.
if(success) {
// 로그인 성공
//ilocalUser.userName = 플레이어 이름
//ilocalUser.id = 플레이어 아이디
//ilocalUser.state = 플레이어 상태
//ilocalUser.underage = 플레이어 미성년자 여부
} else {
// 로그인 실패
}
});
GPGSManager.Instance.Logout(); // 로그아웃합니다.
도전과제
GPGSManager.Instance.ShowAchievementsUI(); // 모든 도전과제 목록 UI를 표시합니다.
GPGSManager.Instance.RevealAchievement(GPGSIds.ACHIEVEMENTID, 50f, (success) => { // 해당 단계별 도전과제를 업데이트합니다.
if(success) {
// 도전과제 업데이트 성공시
} else {
// 도전과제 업데이트 실패시
}
});
GPGSManager.Instance.UnlockAchievement(GPGSIds.ACHIEVEMENTID, (success) => { // 해당 도전과제를 해금시킵니다.
if(success) {
// 도전과제 해금 성공시
} else {
// 도전과제 해금 실패시
}
});
리더보드
GPGSManager.Instance.ShowLeaderboardUI(GPGSIds.LEADERBOARDID); // 해당 리더보드 UI를 표시합니다.
GPGSManager.Instance.ReportLeaderboard(GPGSIds.LEADERBOARDID, 123, (success) => { // 해당 리더보드에 점수를 기록합니다.
if(success) {
// 리더보드 점수 기록 성공시
} else {
// 리더보드 점수 기록 실패시
}
});
이벤트
GPGSManager.Instance.FetchEvent(GPGSIds.EVENTID, (success, ievent) => { // 해당 이벤트 목록을 표시합니다.
if(success) {
// 이벤트 목록 표시 성공시
} else {
// 이벤트 목록 표시 실패시
}
});
GPGSManager.Instance.IncrementEvents((success, ievents) => { // 해당 이벤트를 업데이트합니다.
if(success) {
// 이벤트 업데이트 성공시
} else {
// 이벤트 업데이트 실패시
}
});
클라우드 서비스
using Newtonsoft.Json;
//...
public void SaveWithCloud() {
string serializedData = JsonConvert.SerializeObject(data); // 데이터를 저장하기 전에 직렬화합니다.
GPGSManager.Instance.SaveWithCloud("FILENAME", serializedData, (success) => { // 데이터를 클라우드에 저장합니다.
if(success) {
// 데이터 저장 성공시
} else {
// 데이터 저장 실패시
}
);
}
public void LoadWithCloud() {
GPGSManager.Instance.LoadWithCloud("FILENAME", (success, serializedData) => { // 데이터를 클라우드에서 불러옵니다.
if(success) {
// 데이터 로드 성공시
Data data = JsonConvert.DeserializeObject<Data>(serializedData); // 불러온 데이터를 역직렬화합니다.
} else {
// 데이터 로드 실패시
}
});
}
public void DelectWithCloud() {
GPGSManager.Instance.DelectWithCloud("FILENAME", (success) => { // 데이터를 클라우드에서 삭제합니다..
if(success) {
// 데이터 삭제 성공시
} else {
// 데이터 삭제 실패시
}
});
}