[Steam] Cloud API 이용하여 클라우드에 게임 저장하기

환경: Unity 2020.3 / Steamworks.NET

Steam Cloud를 이용하는 방식은 크게 두 가지이다.  Auto-Cloud와 Cloud API로 나눠 볼 수 있는데, Auto-Cloud는 단어의 의미대로 지정한 폴더를 통째로 동기화 해주는 방식이다.  스팀 메뉴얼 대로 세팅만 잘 하면 문제 없이 연동 가능하다.  아마도 인디 개발을 하면서 빠르게 Cloud 적용이 필요할 때 사용하면 좋을 것 같다.  오늘은 Auto-Cloud가 아닌 Cloud API에 관한 이야기이다.

기본 세팅은 Steamworks 어드민에서 Application > Steam Cloud 메뉴를 통해 시작한다.  우선 각 유저 별 최대 허용 사이즈와 최대 파일 개수를 세팅해보자.

유저 별 최대 파일 사이즈는 100G이고 최대 파일 개수는 1만개이다.  이것이 게임 별 할당량으로 보일수도 있는데 유저 별 할당량이다.  게임에 대한 최대 할당량은 명확히 명시가 되어 있지 않다.  각 할당량을 세팅하면 Cloud API에 대한 설정은 거의 끝난 것이라고 보면 된다.  Dynamic Cloud Sync도 특별한 이유가 아니라면 Enable시켜두자. (Steam Deck같은 장비에서 잠시 화면이 꺼지는 Suspend상태에서도 Cloud와 동기화 시킬 수 있는 기능)

Auto-Cloud에 비해 설정할 것이 별로 없다.  다만 Cloud API를 사용하는 코드가 추가될 뿐.

저장을 위해 사용한 API은 다음과 같다.

//여러 파일들을 한번에 저장할 때 EndFileWriteBatch로 감싸주도록 한다.
Steamworks.SteamRemoteStorage.BeginFileWriteBatch();  

//총 할당량과 현재 남은 용량을 조회할 수 있다.
Steamworks.SteamRemoteStorage.GetQuota(out totalBytes, out availableBytes);  

//실제 클라우드에 저장을 위한 함수이지만 동기화를 위해 별도의 장소에 저장을 해둔다.  실제로 네트워크를 통한 동기화는 이 시점에서는 진행하지 않는다.  비동기나 동기 여부에 따라 FileWriteAsync 또는 FileWrite를 사용한다.  fileStr은 경로가 아니라 저장하는 파일의 이름과 확장자만을 포함해야 한다. (ex. savedata.dat)
Steamworks.SteamRemoteStorage.FileWriteAsync(fileStr, writeBytes, writeLength); 

//BeginFileWriteBatch()를 사용했다면 이 함수로 마무리한다.
Steamworks.SteamRemoteStorage.EndFileWriteBatch();  

위의 API를 이용하여 저장을 마쳤다면, 저장된 파일은 어디에 위치하는 것일까.  바로 네트워크를 통해 Steam Cloud 계정에 저장이 되었을까?  만약 네트워크가 끊겨있는 상황이라면?  FileWrite할 때 경로를 지정하지 않았는데? 같은 의문이 들 수 있다.

파일 탐색기를 열어 C:\Program Files (x86)\Steam\userdata로 이동해보자.  userdata에 있는 숫자 폴더들은 AccountID에 따라 구분된 폴더들이다.  AccoutID는 Steamworks.SteamUser.GetSteamID().GetAccountID()를 통해 확인 할 수 있다. 

본인의 AccoundID 폴더에 들어가면 다시 숫자들 폴더가 나오는 데, 이 숫자들의 의미는 게임 ID (Steamworks 연동할 때 사용하는 ID)이다.  게임 ID를 찾아 다시 들어가 보면, remote라는 폴더가 있고 그 안에 Steamworks.SteamRemoteStorage.FileWrite API를 통해 저장한 파일들의 목록을 볼 수 있다.

즉, 네트워크의 연결과 상관없이 오프라인 상태에서도 클라우드용 데이터는 로컬에 저장이 된다.  이를 통해 네트워크가 연결이 된 상태로 변경 되어 동기화가 필요할 때 최신의 데이터로 동기화를 진행할 수 있게 된다.  그리고 Steam Client 설정에 클라우드 동기화를 On/Off로변경할 수 있는데, 이 설정과도 관계없이 클라우드용 데이터는 계속 저장될 필요가 있다.   Steamworks.SteamRemoteStorage.IsCloudEnabledForApp()와 Steamworks.SteamRemoteStorage.IsCloudEnabledForAccount()는 Steam Client의 클라우드 설정 On/Off 상태를 체크할 수 있는 API이다.  이 API는 저장시에는 사용하지 않아야 한다.  클라우드 설정이 Off에서 On되었을 때 그동안의 저장된 데이터를 클라우드에 올릴 수 있기 때문이다.

이제 저장된 데이터를 로드해보자.

이때는 Steam Client의 클라우드 설정 상태를 조회해 볼 필요가 있다.  본인이 클라우드 데이터를 원하지 않는 데 클라우드에 저장된 데이터를 덮어 쓸 수는 없기 때문에 위에서 언급한 API(IsCloudEnabledForApp() / IsCloudEnabledForAccount())를 사용하여 상태를 체크한다.  만약 세팅이 On 상태라면 클라우드에 저장된 데이터를 로드해오면 된다.

로드에 사용하는 API는 다음과 같다.

//실제로 파일이 remote 폴더 안에 있는지 확인한다.
Steamworks.SteamRemoteStorage.FileExists(fileStr)

//파일 사이즈를 가져온다. 
int byteSize = Steamworks.SteamRemoteStorage.GetFileSize(fileStr);

//파일 사이즈에 맞게 버퍼를 생성한다.
byte[] readData = new byte[byteSize];

//저장된 데이터를 읽어와서 버퍼에 저장한다.
 Steamworks.SteamRemoteStorage.FileRead(aFileName, readData , readData.Length);

이제 버퍼에 읽어온 데이터를 이용하여 게임을 진행할 수 있다.

게임 진행에 필요한 저장과 로드에 대해 알아보았다.  이제 게임 실행 전에 Steam Client에서 이루어 지는 동기화 과정에 대해 간단히 살펴보자.

Steam Client에서 플레이 버튼을 누르기 전에 remote 폴더 안의 파일들과 클라우드에 올라가 있는 파일들 사이에 동기화가 이루어 진다.  이때 파일들의 저장 우선 순위가 모호할 때 충돌 해결 창이 뜨는데, 이는 Steam Client에서 자체적으로 발생시키는 프로세스이다.  즉, 내가 원한다고 해서 충돌 해결 창을 띄우는 것은 불가능하다.

위의 창에서 선택하는 옵션에 따라 remote 폴더 안에 파일들의 상태가 달라지는데, 클라우드 저장 데이터 옵션을 선택할 경우 클라우드에 존재하는 파일들을 다운로드 받아 로컬 폴더(remote 폴더)에 덮어 쓰게 된다.  반면, 로컬 저장 데이터 옵션을 선택할 경우 로컬 파일을 업로드 하여 클라우드 데이터를 덮어쓰고 동기화 과정을 마친다.

정리하면, 클라우드 동기화 -> 로드 -> 게임 플레이 -> 저장의 과정으로 보면 될 것 같다.  클라우드가 진행되는 과정에 대한 로그는 C:\Program Files (x86)\Steam\logs\cloud_log.txt 파일에서 확인 가능하다.

Leave a Reply

Your email address will not be published. Required fields are marked *