본문 바로가기
유니티 최고/유니티 구현

[Unity] 유니티 데이터 저장하기[2] - (모바일 GPGS를 이용한 저장방법)

by Lee_story_.. 2024. 6. 6.
728x90

 

 

앞선 글에서는 유니티에서 제공해주는 PlayerPrefs를 이용하여 데이터를 로드/ 세이브 해보았습니다. 

유니티에서 제공해주는 만큼 구현이 쉽다는 장점이 있었지만, 보안에 대한 문제가 있어 암호화하여 처리해 보았습니다. 

 

 

[Unity] 유니티 데이터 저장하기[1] - (PlayerPrefs + 암호화)

유니티를 이용해서 게임/ 어플리케이션을 제작할 경우 생성되는 데이터들...저 역시 개발을 진행 할 수록 어플리케이션이 종료되어도 유지되는 데이터들을어딘가에 저장해야하는 상황이 발생

ljhyunstory.tistory.com

 

 

단순한 정보에 대해서는 상관없지만... 개인정보나 주요 재화의 경우에는 약간 불안한 느낌을 지울 수 없었습니다...

 

그래서 다른 방법들을 찾아보면서,

모바일 게임의 경우에 사용할 수 있는 GPGS를 이용하여 데이터를 저장하는 방법을 사용하게 되어, 정리해 보았습니다

 

 

그럼 시작해보겠습니다!

 

 

가장 먼저

 

 

GPGS란..?


GPGS란 구글 플레이 게임 서비스의 약자로,

안드로이드에서 운용가능한 어플리케이션을 개발하는데 필요한 기능들을 지원하는 구글의 소프트웨어 개발 키트입니다. 

 

여기까지만 들어보면 정확히 어떤 내용의 개발키트인지 감이 오지않는데.... 모바일 게임을 플레이할 때를 생각하여봅시다.

 

모바일 게임을 가장 먼저 실행하면,

온라인 요소가 들어간다던가, 랭킹 들의 요소가 첨가된 게임의 경우에,

따로 로그인을 하거나, 계정을 연동하는 등의 단계를 거치게 됩니다. 

 

그런데 어떤 게임의 경우에는 실행하면서 아무런 조작없이도,
아래와 같이 로그인 되는 것을 볼 수 있습니다.

 

 

이게 어떤 것인지에 대해서는 깊게 생각해본적이 없었는데...

이것이 GPGS를 이용한 가장 기초적인 기능!  계정 연동입니다. 

 

 

계정연동에 대해서, 데이터 베이스를 연결하고 관리하고 기능을 구현하는데에는 상당한 시간과 비용이 발생하는데...

GPGS를 이용하면 간단하게 사용자의 구글계정, 정확히는 Google Play 게임계정을 사용하여

게임 계정으로써 사용할 수 있습니다. 

 

 

이를 위해서 설정해줘야하는 부분이 많지만, 계정 연동 외에도 업적, 랭킹 등의 기능들을 사용할 수 있습니다!

(저는 이런 기능들을 GPGS로 구현할 수있다는것을 너무 늦게 알아버려...서 거의 갈아엎어버린....)

 

기능들 자체도 생각보다 쉽게 사용할 수 있었고, 코드 자체도 이미 만들어져 있는 라이브러리를 사용하는 느낌 이였습니다.

 

 

 

제가 사용해본 기능들은 하나 하나씩 정리하여 업로드하겠습니다. 

오늘은 GPGS 설정과 로그인만!

 

 

하지만 잠깐!

 

*아마 다들 출시를 생각하시고 개발을 진행하고 계신다고 생각하고 설명을 진행할 예정입니다. 

이는 GPGS를 사용하는데에 구글 개발자 계정이 필요하기 때문입니다...

 

그렇기 때문에! 25달러의 구글 개발자 계정에 대해 생각이 없으시다면 GPGS는 사용하지 못합니다.. 돌아가기...

 

 

하지만 출시 하실 예정이라면 계속해서 진행하시면 될 것 같습니다.

 

 

 

시작!


그럼 빠르게 설정해보겠습니다!  (프로젝트는 당연히 안드로이드로 스위칭 하셨죠??)

 

- GPGS 설치 -

 

가장 먼저 아래 GPGS파일을 받아줍시다. 

 

GitHub - playgameservices/play-games-plugin-for-unity: Google Play Games plugin for Unity

Google Play Games plugin for Unity. Contribute to playgameservices/play-games-plugin-for-unity development by creating an account on GitHub.

github.com

 

 

그리고 그 파일을 풀어준 뒤, current-build의 구글플레이 플러그인을 임포트해줍시다. 

 

 

 

그러면 아래처럼 뜨게되는데, 변경사항을 적용할 것인지에 대한 창입니다. 

Enable 클릭!

 

 

그러면 자동으로 변경해줍니다.

 

 

적용이 끝나고나면

다시 한번 Resolve하여 변경사항을 적용되었는지 확인합니다!

 

 

 

아래 처럼 뜨면 끝!

 

 

안된다면... 해당 프로젝트의 파일에서 아래경로로 이동

~ 프로젝트파일\Assets\GooglePlayGames\com.google.play.games\Editor

 

GooglePlayGamesPluginDependencies.xml 파일에서

 

 

repository 부분의 경로를 Assets/GooglePlayGames/ ~ 로 변경해주고 다시 Resolve 진행해줍시다!

...
        <repository>Assets/GooglePlayGames/com.google.play.games/Editor/m2repository</repository>
....

 

 

 

- GPGS 준비준비.. -

 

이 상태로 바로 계정 연동기능을  구현하게 되면 당연히 fail.... 실패하게 됩니다. 구글플레이 게임즈 코드가 없기 때문!

 

 

그렇기에 아래와 같은 단계가 필요합니다

- 개발자 계정 등록

- 앱 등록  (*abb파일은 )

- 키스토어 생성

- gpgs 추가

등등....

 

 

아마 3번째 글만 참고하면 될 것 같은데... 그래도 출시하실 예정이라면 3개의 글을 차례대로 읽어주시면 감사하겠습니다!

 

 

구글 플레이 Unity 게임 출시를 위한 준비 [1] (구글 개발자 계정부터 내부 테스트 까지)

이번에 처음으로 구글 플레이에 간단한? 게임을 출시해보고자 시작한 프로젝트가 벌써 2달정도 진행되고 끝이 보이는것 같아요! ㅎㅎ 이제 프로젝트가 후반부로 가는만큼, 개발보다는 출시를

ljhyunstory.tistory.com

 

 

 

구글 플레이 Unity 게임 출시를 위한 준비 [2] (게임 설정과 비공개 테스트 그리고 프로덕션)

준비준비 단계가 많이 힘드네요.... 그래도 화이팅! 해서 해보도록 하겠습니다.   기본 게임 설정 시작!기본 게임 설정은 정말 기본적인 것들로 따로 설정해줄 것 없이 자신의 어플리케이션에

ljhyunstory.tistory.com

 

 

구글 플레이 Unity 게임 출시를 위한 준비 [3] (GPGS 설정)

이 부분은 유니티에서 GPGS를 설정하기 위한 부분으로 구글 플레이 준비준비로 글을 3개나 쓸 줄 몰랐네요...아무튼 시작!  GPGS설정 시작!여기서부터는 약간 어지러울 수도...콘솔창과 클라우드

ljhyunstory.tistory.com

 

 

 

그럼 위에서의 세팅이 끝나셨다면 이어 시작하겠습니다. 

(글을 쓰다 보니 순서가 꼬여버렸네요... )

 

위 글에서 설명을 했겠지만

 

아래의 id와 플레이콘솔 리소스를 추가해야 사용가능합니다!

 

 

리소스는 구글 콘솔 사이트에서!

 

클라이언트 ID는 구글 클라우드에서!

 

 

 

- GPGS 코드!-

 

 

그럼 이제 마지막 구글 플레이 게임 계정에 대한 로그인 코드!

코드자체는 매우매우 간단합니다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using GooglePlayGames;
using GooglePlayGames.BasicApi;
using GooglePlayGames.BasicApi.SavedGame;

public class GoogleManager : MonoBehaviour
{

    // Start is called before the first frame update
    void Start()
    {
        PlayGamesPlatform.DebugLogEnabled = true;
        PlayGamesPlatform.Activate();
        SignIn();
    }

    public void SignIn()
    {
        PlayGamesPlatform.Instance.Authenticate(ProcessAuthentication);
    }



    // 구글 로그인!
    internal void ProcessAuthentication(SignInStatus status)
    {
        if(status== SignInStatus.Success)
        {
            Debug.Log("굳");
        }
        else
        {

            Debug.Log("실패");
            //GameManager.instance.DataSave_Scr.LoadUserDataFun();
        }
    }
}

 

PlayGamesPlatform.Activate() 로 설정을 해주고

PlayGamesPlatform.Instance.Authenticate(ProcessAuthentication)를 이용해서 로그인을 실행한뒤,

결과를 ProcessAuthentication() 함수로 전달하여 로그인이 완료되었는지 확인하는 코드!

 

 

결과는 아래처럼 앱 실행시 상단에 로그인 ui가 생기게 됩니다!

 

 

 

 

이제 이렇게 연결된 계정에 데이터 값들을 로드, 세이브 하는 코드를 구성해 주겠습니다.

 

 

 

먼저 저장하는 코드!

 

데이터 저장


코드 구성 자체는 크게 3개의 함수로 구성되어있습니다.

[OpenSaveGame]		- OpenWithAutomaticConflictResolution를 통한 데이터 접근 함수

[onsavedGameOpend]	- 저장하고자하는 데이터 json 변환 / 데이터 업데이트 함수 CommitUpdate 실행 함수

[OnSavedGameWritten]	- 데이터 저장 성공여부 판단 함수

 

 

코드는 아래처럼!

public void SaveData() // 외부에서 접근할 함수
    {
        OpenSaveGame();
    }


    private void OpenSaveGame()
    {
        ISavedGameClient saveGameClient = PlayGamesPlatform.Instance.SavedGame;
		
        // 데이터 접근
        saveGameClient.OpenWithAutomaticConflictResolution(fileName,
            DataSource.ReadCacheOrNetwork,
            ConflictResolutionStrategy.UseLastKnownGood,
            onsavedGameOpend);
    }


    private void onsavedGameOpend(SavedGameRequestStatus status, ISavedGameMetadata game)
    {
        ISavedGameClient saveGameClient = PlayGamesPlatform.Instance.SavedGame;

        if (status == SavedGameRequestStatus.Success)
        {
            var update = new SavedGameMetadataUpdate.Builder().Build();

            //json
            var json = JsonUtility.ToJson("저장하려는 데이터!");
            byte[] data = Encoding.UTF8.GetBytes(json);
            
            // 저장 함수 실행
            saveGameClient.CommitUpdate(game, update, data, OnSavedGameWritten);
        }
        else
        {
            Debug.Log("Save No.....");
        }
    }
	
    // 저장 확인 
    private void OnSavedGameWritten(SavedGameRequestStatus status, ISavedGameMetadata data)
    {
        if (status == SavedGameRequestStatus.Success)
        {
        // 저장완료부분
            Debug.Log("Save End");
        }
        else
        {
            Debug.Log("Save nonononononono...");
        }
    }

 

 

 

 

다음은 로드하는 코드!

데이터 로드 


코드 구성은 세이브와 비슷합니다.

[OpenLoadGame]		- OpenWithAutomaticConflictResolution를 통한 데이터 접근 함수

[LoadGameData]		- 저장된 데이터를 ReadBinaryData를 통해 받아오는 함수

[onSavedGameDataRead]	- 저장된 데이터에 대해 인코딩과 데이터 초기화 하는 함수

 

 

public void LoadData()
    {
        OpenLoadGame();
    }

    private void OpenLoadGame()
    {
        ISavedGameClient saveGameClient = PlayGamesPlatform.Instance.SavedGame;

        saveGameClient.OpenWithAutomaticConflictResolution(fileName,
            DataSource.ReadCacheOrNetwork,
            ConflictResolutionStrategy.UseLastKnownGood,
            LoadGameData);
    }

    private void LoadGameData(SavedGameRequestStatus status, ISavedGameMetadata data)
    {
        ISavedGameClient saveGameClient = PlayGamesPlatform.Instance.SavedGame;

        if (status == SavedGameRequestStatus.Success)
        {
            Debug.Log("!! GoodLee");
			
            // 데이터 로드
            saveGameClient.ReadBinaryData(data, onSavedGameDataRead);
        }
        else
        {
            Debug.Log("?? no");
        }
    }

	// 불러온 데이터 처리 
    private void onSavedGameDataRead(SavedGameRequestStatus status, byte[] loadedData)
    {
        string data = System.Text.Encoding.UTF8.GetString(loadedData);

        if (data == "")
        {
            SaveData();
        }
        else
        {
			// 불러온 데이터를 따로 처리해주는 부분 필요!
        }
    }

 

 

모양새도 세이브 부분과 비슷합니다!

추가된 부분을 보면 

1. 저장된 데이터가 없을때 새로운 초기화 데이터를 저장하는 부분

2. 불러온 데이터에 대해서 현재 유니티에 적용시키는 부분

 

이 2가지를 마지막 onSavedGameDataRead함수에 추가해주었습니다. 

이 부분은 저장 데이터 형식에 따라 다르게 작성해주시면 될 것 같습니다.

 

 

+ 추가적으로 데이터 삭제코드!

 

더보기
 public void DeleteData()
    {
        DeleteGameData();
    }

    private void DeleteGameData()
    {
        ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;

        savedGameClient.OpenWithAutomaticConflictResolution(fileName,
            DataSource.ReadCacheOrNetwork,
            ConflictResolutionStrategy.UseLastKnownGood,
            DeleteSaveGame);
    }


    private void DeleteSaveGame(SavedGameRequestStatus status, ISavedGameMetadata data)
    {
        ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;

        if(status == SavedGameRequestStatus.Success)
        {
            savedGameClient.Delete(data);

        }
        else
        {
        }
    }



 

 

 

특정 함수들이 모두 구현되어있어 사용하기만 해주면 데이터 저장/로드를 쉽게 만들수 있었습니다.

모바일 한정이지만 매우매우 도움이 되는 GPGS! 다음에 개발을 시작하면 이것부터 구축해야겠네요...

 

 

 

*코드 자체는 웹상에 많이 존재 했지만 아래 영상에서 좀 더 자세히 깔끔하게 설명해주시는것 같아,

영상링크도 첨부하겠습니다!

 

 

 

 

다음글에서는 업적과 리더보드들을 추가해보겠습니다!

 

 

 


틀린점이 있다면 댓 달아주세요!

댓글