2015년 10월 30일 금요일

구글플레이 게임서비스 클라우드저장 기능 사용해 보기(Google play game service saved game)

 던전워즈

구글플레이 서비스에서 유용한점 하나가 클라우드 저장기능입니다.
서버가 없는 게임인경우 게임데이터를 구글클라우드 서버에 저장하거나 가져오기를 통해서 사용자의 데이터를 안전하게 보관할 수 있습니다.

아래 주소에서 유니티용 플러그인을 다운로드 할 수 있습니다.
https://github.com/playgameservices/play-games-plugin-for-unity

구글플레이 게임서비스 이용에 관한 전반적인 사항은 검색을 통해서 확인하시기 바랍니다.

클라우드 저장기능사용에 대한 핵심적인 부분만 코드로 보여드립니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
using UnityEngine;
using System.Collections;
using GooglePlayGames;
using GooglePlayGames.BasicApi;
using GooglePlayGames.BasicApi.SavedGame;
public static class CGoogleplayGameServiceManager
{
    //게임서비스 플러그인 초기화시에 EnableSavedGames()를 넣어서 저장된 게임 사용할 수 있게 합니다.
    //주의 하실점은 구글플레이 개발자 콘솔의 게임서비스에서 해당게임의 세부정보에서 저장된 게임 사용을 
    //하도록 설정하셔야 합니다.
    public static void Init()
    {
        PlayGamesClientConfiguration config = new PlayGamesClientConfiguration.Builder().EnableSavedGames().Build();
        PlayGamesPlatform.InitializeInstance(config);
        //
        PlayGamesPlatform.DebugLogEnabled = false;
        //Activate the Google Play gaems platform
        PlayGamesPlatform.Activate();
    }
    //인증여부 확인
    public static bool CheckLogin()
    {
        return Social.localUser.authenticated;
    }
    //--------------------------------------------------------------------
    //게임 저장은 다음과 같이 합니다.
    public static void SaveToCloud()
    {
        if (!CheckLogin()) //로그인되지 않았으면
        {
            //로그인루틴을 진행하던지 합니다.
            return;
        }
        //파일이름에 적당히 사용하실 파일이름을 지정해줍니다.
        OpenSavedGame("사용할파일이름"true);
    }
    static void OpenSavedGame(string filename, bool bSave)
    {
        ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;
        if (bSave)
            savedGameClient.OpenWithAutomaticConflictResolution(filename, DataSource.ReadCacheOrNetwork, ConflictResolutionStrategy.UseLongestPlaytime, OnSavedGameOpenedToSave); //저장루틴진행
        else
            savedGameClient.OpenWithAutomaticConflictResolution(filename, DataSource.ReadCacheOrNetwork, ConflictResolutionStrategy.UseLongestPlaytime, OnSavedGameOpenedToRead); //로딩루틴 진행
    }
    //savedGameClient.OpenWithAutomaticConflictResolution호출시 아래 함수를 콜백으로 지정했습니다. 준비된경우 자동으로 호출될겁니다.
        static void OnSavedGameOpenedToSave(SavedGameRequestStatus status, ISavedGameMetadata game)
        {
            if (status == SavedGameRequestStatus.Success)
        {
            // handle reading or writing of saved game.
                //파일이 준비되었습니다. 실제 게임 저장을 수행합니다.
                //저장할데이터바이트배열에 저장하실 데이터의 바이트 배열을 지정합니다.
                SaveGame(game, "저장할데이터바이트배열", DateTime.Now.TimeOfDay);
        }
        else
        {
            //파일열기에 실패 했습니다. 오류메시지를 출력하든지 합니다.
        }
    }
    static void SaveGame(ISavedGameMetadata game, byte[] savedData, TimeSpan totalPlaytime)
    {
        ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;
        SavedGameMetadataUpdate.Builder builder = new SavedGameMetadataUpdate.Builder();
        builder = builder
            .WithUpdatedPlayedTime(totalPlaytime)
            .WithUpdatedDescription("Saved game at " + DateTime.Now);
        /*
        if (savedImage != null)
        {
            // This assumes that savedImage is an instance of Texture2D
            // and that you have already called a function equivalent to
            // getScreenshot() to set savedImage
            // NOTE: see sample definition of getScreenshot() method below
            byte[] pngData = savedImage.EncodeToPNG();
            builder = builder.WithUpdatedPngCoverImage(pngData);
        }*/
        SavedGameMetadataUpdate updatedMetadata = builder.Build();
        savedGameClient.CommitUpdate(game, updatedMetadata, savedData, OnSavedGameWritten);
    }
    static void OnSavedGameWritten(SavedGameRequestStatus status, ISavedGameMetadata game)
    {

        if (status == SavedGameRequestStatus.Success)
        {
            //데이터 저장이 완료되었습니다.
        }
        else
        {
            //데이터 저장에 실패 했습니다.
        }
    }
    //----------------------------------------------------------------------------------------------------------------
    //클라우드로 부터 파일읽기
    public static void LoadFromCloud()
    {
        if (!CheckLogin())
        {
            //로그인되지 않았으니 로그인 루틴을 진행하던지 합니다.
            return;
        }
        //내가 사용할 파일이름을 지정해줍니다. 그냥 컴퓨터상의 파일과 똑같다 생각하시면됩니다.
        OpenSavedGame("사용할파일이름"false);
    }
    static void OnSavedGameOpenedToRead(SavedGameRequestStatus status, ISavedGameMetadata game)
    {
        if (status == SavedGameRequestStatus.Success)
        {
            // handle reading or writing of saved game.
            LoadGameData(game);
        }
        else
        {
            //파일열기에 실패 한경우, 오류메시지를 출력하던지 합니다.
        }
    }
    //데이터 읽기를 시도합니다.
    static void LoadGameData(ISavedGameMetadata game)
    {
        ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;
        savedGameClient.ReadBinaryData(game, OnSavedGameDataRead);
    }
    static void OnSavedGameDataRead(SavedGameRequestStatus status, byte[] data)
    {
            if (status == SavedGameRequestStatus.Success)
            {
                // handle processing the byte array data
                //데이터 읽기에 성공했습니다.
                //data 배열을 복구해서 적절하게 사용하시면됩니다.
            }
            else
            {
                //읽기에 실패 했습니다. 오류메시지를 출력하던지 합니다.
            }
    }
}
cs

댓글 14개:

  1. ShowActionBar(false, true); << 여기서 네임을 찾을 수 없다고 하는데요.. 알수있을까요?

    답글삭제
    답글
    1. 해당 코드는 구글플레이 게임서비스와 관련없는 코드입니다. 단지 UI에서 로딩바 같은걸 보여주거나 숨기거나 하는 코드인데, 그냥 삭제하셔도 됩니다.

      삭제
  2. 콘솔에서 저장된게임을 사용으로 하였고 업로드도 하였는데
    NotImplementedException: You must enable saved games before it can be used. See PlayGamesClientConfiguration.Builder.EnableSavedGames.
    이러한 오류가 뜨는 이유를 알 수 있을까요

    답글삭제
    답글
    1. PlayGamesClientConfiguration config = new PlayGamesClientConfiguration.Builder().EnableSavedGames().Build(); 이부분을 추가 하셨나요? 현재 유니티플러그인이 버전업되서 무너가 변경사항이 있는지 모르겠는데, 빌드 컨피그 설정하실때 위코드처럼 EnableSavedGames()을 활성화 하셔야 할거 같네요.

      삭제
  3. 혹시 지금 보실지 안보실지 모르시겟지만 궁금해서 한번올려봅니다 ~
    혹시 저기에 플레이어 정보 데이터를 따로 불러와서 저장을 해야되는건가요 ? 아니면 그냥 위에있는 스크립트만 구글플레이에 연동하면 저절로 모든 게임 데이터가 저장되는건가요 ? 궁금하네요

    답글삭제
  4. 제 질문이 이해되실지 몰라서 추가로 질문설명 드리겟습니다 ㅠ.. 제 질문은 만약에 int PlayerPower/ int PlayerSTR 이런식으로 플레이어 데이터가있는데 그데이터를 따로 저기에다가 어디다가 써야 저장이되냐 이질문입니다.... ! 구글링해도 안보여서 질문해봅니당 ㅠ

    답글삭제
    답글
    1. 구글플레이 클라우드 저장기능은 바이트 배열을 파일형태로 구글클라우드 서버에 저장하거나 가져올 수 있게 하는 기능을 제공해줍니다. 파일 입출력에 대한 기본지식이있으시다면 이해하기가 좀더 수월할겁니다. 코드 내용중에 보시면 SaveGame(game, "저장할데이터바이트배열", DateTime.Now.TimeOfDay); 라는 부분이 있습니다. 두번째인자로 저장할데이터의 바이트 배열이라는 부분에 저장할 플레이어 데이터를 직렬화한 바이트 배열을 지정하면되고 복구시에는 위코드중에 OnSavedGameDataRead(SavedGameRequestStatus status, byte[] data)
      라는 함수에서 data로 전달되는 인자가 이전에 SaveGame함수에서 지정했던 직렬화 했던 플레이어 데이터의 바이트 배열입니다. 이걸 다시 역질렬화를 통해서 복구해서 사용해야 합니다. 결론은 클라우드 저장기능은 바이트 배열을 저장하고 다시 읽을수 있는 기능을 제공할 뿐입니다. 플레이어 데이터를 직렬화해서 저장하고, 저장된 데이터를 다시 역직렬화해서 다시 사용하는 부분은 직접 구현을 해주셔야 합니다. 예를 들면 플레이어 데이터를 json형식의 문자열로 변환해서 문자열을 바이트화해서 저장한다음 다시 읽을때는 바이트화된 문자열을 다시 json으로 복구해서 플레이어데이터를 복구한다음 게임에 사용할 수 있게 할 수 도 있겠습니다.

      삭제
    2. 그러면 굳이 json을 이용하지않고 유니티안에있는 직렬화로 해줘도 되는건가요 ?

      삭제
    3. 그리고 굳이 json을 이용한다면 구글 클라우드 세이브 기능을 이용하지않고도 저장이 가능한데 왜 구글 클라우드를 이용하는거죠 ?

      삭제
    4. json형태로 사용하고 직렬화하는경우는 한가지예일뿐입니다. 저장할 데이터를 바이트 배열로 직열화해서 저장하고 다시 가져와서 복구할 수만 있다면 어떤 방법을 이용하던지 관계없습니다. 구글 클라우드 저장기능을 이용하는 이유는 서버가 없는 클라이언트만으로 구성된 게임에서 데이터이터를 구글의 서버측에 백업하거나 백업된 데이터를 다시 가져와서 사용하는 용도에 이용하기 적합하다고 생각됩니다.

      삭제
    5. 그렇군용... 답변 정말 감사합니다 도움이 많이 되었습니다.

      삭제
  5. 작성자가 댓글을 삭제했습니다.

    답글삭제
  6. 혹시 지금도 답변이 가능할까요...
    윗글에서 24번째줄 savedGameClient.OpenWithAutomaticConflictResolution(filename, DataSource.ReadCacheOrNetwork, ConflictResolutionStrategy.UseLongestPlaytime, OnSavedGameOpenedToSave); 이 부분에서 OnSavedGameOpenedToSave를 실행하질 않는 것 같은데 도무지 이유를 모르겠네요 ㅠㅠ
    혹시 아신다면 답변해주시면 감사하겠습니다.

    답글삭제
    답글
    1. savedGameClient.OpenWithAutomaticConflictResolution도 작동하는지 잘 모르겠네요

      삭제