【发布时间】:2019-04-02 09:29:23
【问题描述】:
我正在使用 Unity 开发一款用于移动设备的多人文字游戏。我一直使用 GameSparks 作为后端,但觉得它并没有给我想要的项目控制权。环顾四周后,我决定使用 Firebase。感觉是个不错的决定,但现在我在使用数据库 + 云功能时遇到了一些严重的缓慢
游戏具有回合制模式,您可以在其中玩一局并在对手完成时收到通知。一轮通过 cloudscript 调用上传,仅包含必要的数据。然后在 cloudscript 中拼凑新的游戏状态,并更新游戏数据库条目 (activeCasualGames/{gameId})。完成后,我用一些关于游戏的基本信息更新了一个 gameInfo (activeCasualGamesInfo/{gameId}) 条目,然后发送一条云消息通知对手轮到他们了。
发送的数据只有32kb,没有对代码做复杂的改动(见下方云函数代码)。此时游戏的完整数据库条目最大约为 100kb,但从发送回合到游戏在服务器上更新并通知对手的时间从 50 秒到超过一分钟不等。在 GameSparks 上,相同的操作可能需要几秒钟。
还有其他人在使用 Firebase 时遇到这种缓慢的情况吗?我在云脚本功能中犯了一些错误,还是我应该期待的性能?游戏还有一个实时模式,我还没有开始在 Firebase 中实现它,而且由于这种滞后,我觉得它的效果不会太好
非常感谢!
exports.uploadCasualGameRound = functions.https.onCall(
(roundUploadData, response) => {
const roundData = JSON.parse(roundUploadData);
const updatedGameData = JSON.parse(roundData.gameData);
const updatedGameInfo = JSON.parse(roundData.gameInfo);
console.log("game data object:");
console.log(updatedGameData);
console.log("game info:");
console.log(updatedGameInfo);
const gameId = updatedGameData.gameId;
console.log("updating game with id: " + gameId);
admin
.database()
.ref("/activeCasualGames/" + gameId)
.once("value")
.then(function(snapshot: { val: any }) {
let game = snapshot.val();
console.log("old game:");
console.log(game);
const isNewGame = (game as boolean) === true;
if (isNewGame === false) {
console.log("THIS IS AN EXISTING GAME!");
} else {
console.log("THIS IS A NEW GAME!");
}
// make the end state of the currently stored TurnBasedGameData the beginning state of the uploaded one (limits the upload of data and prevents timeout errors)
if (isNewGame === true) {
updatedGameData.gameStateRoundStart.playerOneRounds =
updatedGameData.gameStateRoundEnd.playerOneRounds;
} else {
// Player one rounds are not uploaded by player two, and vice versa. Compensate for this here:
if (updatedGameData.whoseTurn === updatedGameData.playerTwoId) {
updatedGameData.gameStateRoundEnd.playerTwoRounds =
game.gameStateRoundEnd.playerTwoRounds;
} else {
updatedGameData.gameStateRoundEnd.playerOneRounds =
game.gameStateRoundEnd.playerOneRounds;
}
updatedGameData.gameStateRoundStart = game.gameStateRoundEnd;
}
game = updatedGameData;
console.log("Game after update:");
console.log(game);
// game.lastRoundFinishedDate = Date.now();
game.finalRoundWatchedByOtherPlayer = false;
admin
.database()
.ref("/activeCasualGames/" + gameId)
.set(game)
.then(() => {
updatedGameInfo.roundUploaded = true;
return admin
.database()
.ref("/activeCasualGamesInfo/" + gameId)
.set(updatedGameInfo)
.then(() => {
exports.sendOpponentFinishedCasualGameRoundMessage(gameId, updatedGameInfo.lastPlayer, updatedGameInfo.whoseTurn);
return true;
});
});
});
}
);
【问题讨论】:
-
在设计 Firebase 数据库时尽量保持扁平的层次结构不要使用嵌套结构,即使 Firebase 支持嵌套结构它也会变慢
-
这个函数的完整代码有点难以理解。你能用更少的代码和硬编码的数据重现这个问题吗?这将允许其他人看到正在发生的一切,并可能尝试重现问题。另请查看how to create a minimal, complete, verifiable example。
-
非常感谢您的意见。我与 Firebase 支持部门取得了联系,并从他们那里得到了令人惊讶的快速回复。当我知道更多时,我会在这里写下结论。 @Shanmugam:您可能在这里有所收获。游戏数据对象非常复杂且嵌套很深,遗憾的是很难做很多事情。
-
@FrankvanPuffelen:感谢您的意见。我会看看你发布的链接!
标签: node.js firebase firebase-realtime-database google-cloud-functions