【发布时间】:2016-11-16 14:47:09
【问题描述】:
在我的游戏中,我有游戏内货币,我想将其价值保存到云端。我决定使用 Google Saved Games API。一切都很好,但是当我将数据保存到快照中,然后在游戏再次启动时读取它时,即使我在同一台设备上,我也会遇到冲突。现在我在每次更改后保存货币的状态,所以当玩家花费或获得一些“硬币”时。我在想这可能经常发生并且服务无法处理它,因为当我离线时(没有连接到网络)一切都很好而且很快,但是当我在线时(连接到 Wi-fi)可以使用快照速度较慢,正如我所说,我与上次保存的数据和以前保存的数据发生冲突(我正在记录所有值......)。有时我什至会遇到 5 个冲突。我有 3 个函数可用于保存的游戏。一种用于读取数据,一种用于保存数据,一种用于检查冲突:
读取数据:
private void readSavedGame(final String snapshotName) {
AsyncTask<Void, Void, Boolean> readingTask = new AsyncTask<Void, Void, Boolean>() {
@Override
protected Boolean doInBackground(Void... params) {
Snapshots.OpenSnapshotResult result = Games.Snapshots.open(mGoogleApiClient, snapshotName, false).await();
Snapshot snapshot = processSnapshotOpenResult(result, 0);
if(snapshot != null) {
try {
updateGameData(snapshot.getSnapshotContents().readFully());
Log.d(TAG, "Updating game: "+String.valueOf(coins)+"...");
return true;
} catch (IOException e) {
Log.d(TAG, "Error: " + e.getMessage());
}
}
return false;
}
@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
if(result) Log.d(TAG, "Game state read successfully...");
else Log.d(TAG, "Error while reading game state...");
updateUi();
}
};
readingTask.execute();
}
保存数据:
private void writeSavedGame(final String snapshotName, final byte[] data) {
AsyncTask<Void, Void, Boolean> updateTask = new AsyncTask<Void, Void, Boolean>() {
@Override
protected Boolean doInBackground(Void... params) {
Snapshots.OpenSnapshotResult result = Games.Snapshots.open(
mGoogleApiClient, snapshotName, false).await();
Snapshot snapshot = processSnapshotOpenResult(result, 0);
if(snapshot != null) {
snapshot.getSnapshotContents().writeBytes(getGameData());
Log.d(TAG, "Saving: "+String.valueOf(coins)+"...");
Snapshots.CommitSnapshotResult commitSnapshotResult = Games.Snapshots.commitAndClose(mGoogleApiClient, snapshot, SnapshotMetadataChange.EMPTY_CHANGE).await();
if(commitSnapshotResult.getStatus().isSuccess()) return true;
}
return false;
}
@Override
protected void onPostExecute(Boolean result) {
if (result) Log.d(TAG, "Game was saved successfully....");
else Log.d(TAG, "Error while saving game state...");
}
};
updateTask.execute();
}
检查冲突或处理 OpenSnapshotResult
Snapshot processSnapshotOpenResult(Snapshots.OpenSnapshotResult result, int retryCount) {
Snapshot mResolvedSnapshot = null;
retryCount++;
int status = result.getStatus().getStatusCode();
Log.i(TAG, "Save Result status: " + status);
if (status == GamesStatusCodes.STATUS_OK) {
Log.d(TAG, "No conflict, SNAPSHOT is OK");
return result.getSnapshot();
} else if (status == GamesStatusCodes.STATUS_SNAPSHOT_CONTENTS_UNAVAILABLE) {
return result.getSnapshot();
}
else if (status == GamesStatusCodes.STATUS_SNAPSHOT_CONFLICT) {
Log.d(TAG, "Conflict: "+String.valueOf(retryCount));
Snapshot snapshot = result.getSnapshot();
Snapshot conflictSnapshot = result.getConflictingSnapshot();
// Resolve between conflicts by selecting the newest of the conflicting snapshots.
mResolvedSnapshot = snapshot;
if (snapshot.getMetadata().getLastModifiedTimestamp() <
conflictSnapshot.getMetadata().getLastModifiedTimestamp()) {
mResolvedSnapshot = conflictSnapshot;
}
try {
Log.d(TAG, "Snapshot data: "+new String(snapshot.getSnapshotContents().readFully()));
Log.d(TAG, "Conflicting data: "+new String(conflictSnapshot.getSnapshotContents().readFully()));
} catch (IOException e) {
Log.e(TAG, "ERROR WHILE READING SPAPSHOTS CONTENTS...");
}
Snapshots.OpenSnapshotResult resolveResult = Games.Snapshots.resolveConflict(
mGoogleApiClient, result.getConflictId(), mResolvedSnapshot).await();
if (retryCount < MAX_SNAPSHOT_RESOLVE_RETRIES) {
// Recursively attempt again
return processSnapshotOpenResult(resolveResult, retryCount);
} else {
// Failed, log error and show Toast to the user
String message = "Could not resolve snapshot conflicts";
Log.e(TAG, message);
//Toast.makeText(getBaseContext(), message, Toast.LENGTH_LONG).show();
}
}
// Fail, return null.
return null;
}
很好地解释了冲突原则here。 我的代码基于official docs implementations 和samples。
所以离线时,一切正常,但连接时,我在同一台设备上遇到冲突……也许我经常更新我保存的游戏,而服务无法处理。有任何想法吗?谢谢。
【问题讨论】:
-
你解决了吗?我面临同样的问题。相同的代码在 iCloud 上运行良好,但在 Google 上会产生随机冲突。它与保存频率有关吗?文档的“合理频率”毫无意义。
-
我也遇到了同样的问题,你的最终解决方案是什么?