Com que frequência salvar o estado do jogador em jogos online persistentes?

9

Nos jogos online, as pessoas preferem fazer logon e logoff quando quiserem. Geralmente, as conquistas de seus jogos são salvas perfeitamente no servidor. Isso não é tão difícil de alcançar, mas estou me perguntando como isso pode ser feito de uma maneira eficiente, que faça sentido e seja dimensionada.

Faz sentido salvar as coordenadas do jogador e indicar cada vez que ele é enviado? Meu servidor node.js pode fazer isso facilmente sem bloquear uma resposta, e eu quero empregar um banco de dados Mongo, mas talvez seja mais apropriado fazer isso uma vez por segundo e em um evento em todo o servidor, coletando todos de uma vez?

Lanbo
fonte
Eu salvo o estado do jogo a cada 10 segundos. Eu acho que é o suficiente, isso passa despercebido (e eu estou executando meu servidor MMORPG no meu netbook que tem 512Mb de RAM).
jcora

Respostas:

10

Eu tenho em mente um MMORPG tradicional como o World of Warcraft.

Salve após cada comando de cada jogador e coisa autônoma (por exemplo, NPC)

  • Backup constante. O servidor pode cair a qualquer momento e o estado do jogo é salvo até aquele momento (ou o mais recente possível, de qualquer maneira).
  • Impacto no desempenho do servidor; mesmo que não esteja bloqueando (ou seja, em outro encadeamento), mesmo que o banco de dados esteja em outro servidor, está processando o que você não faria. Se não for bloqueador, como você diz, outro segmento terá que lidar com isso, e esse é um segmento que pode ser ocupado com outra coisa.
  • E / S de disco aumentada, aumentando o risco / taxa de falhas. Isso é especialmente preocupante se você estiver usando SSDs para armazenamento, devido à sua menor vida útil.
  • Se você descarregar o banco de dados para outro servidor, aumentará a largura de banda; isso pode ser uma preocupação se você estiver pagando pela largura de banda e, se não estiver em uma placa de rede separada, estará consumindo recursos que poderiam ser melhor utilizados para lidar com o tráfego do player.
  • O que acontece se o servidor ficar cada vez mais atrasado ao salvar o estado desses comandos? Ou seja, se houver mais comandos do que os que podem ser salvos, eles se acumulam em uma fila? Essa fila transborda e causa um erro? Você para tudo para que a fila possa alcançar?
  • Parece-me que essa abordagem, embora pareça simples, precisaria ser cuidadosamente planejada. Por exemplo, comandos consecutivos que dependem um do outro precisarão ser salvos juntos; caso contrário, uma falha poderá ocorrer no meio dos comandos e apenas um será salvo, mas não o outro. Considere se dois jogadores executam uma troca e dois comandos são salvos no disco: "adicione 1 do item ao destinatário" e "subtraia 1 do item do remetente". Se ocorrer uma falha após o primeiro comando, mas antes que o segundo comando seja salvo, você terá uma duplicação de itens. (se o pedido for revertido, você terá um item perdido)

Salve tudo periodicamente

  • Em caso de falha, o servidor estará um pouco desatualizado. Espero que você use algo como uma abordagem registrada em diário, para que o instantâneo mais recente seja pelo menos completo e consistente, e todos os jogadores ativos sejam recuados pela mesma quantidade de tempo.
  • Qualquer sistema de banco de dados usado pode ter uma otimização para atualização em lote, que é mais eficiente (menos sobrecarga) do que atualizar um de cada vez.
  • Se você optar por um sistema de arquivos binários, esse método será simples. Crie um novo arquivo, despeje memória nele, jogue um marcador no final que sinalize que o backup foi totalmente concluído. Depois que um backup for concluído, exclua o backup anterior (ou não).
  • O processo de backup também pode precisar levar em consideração os itens mencionados no último marcador da outra seção, como salvar no meio de comandos consecutivos que não devem ser divididos. Você pode optar por bloquear todo o conjunto de dados, despejá-lo em disco e desbloqueá-lo, mas, dependendo de quanto tempo leva, isso pode resultar em uma pausa ou desaceleração bastante pesada no jogo.

Salvar um personagem no logout (não salve mais nada)

  • A coisa mais importante para um jogador é seu personagem, que inclui os itens que eles têm, as habilidades que eles ganharam, sua lista de amigos e assim por diante. Se eles matarem um monstro e o saque estiver no chão na frente deles e o servidor falhar, eles ficarão um pouco tristes por não terem a chance de pegar o saque, mas eles vão superar. Portanto, salve as coisas importantes e não se preocupe com as coisas pequenas. Não salve as posições dos NPCs, por exemplo; se o servidor cair, quando ele voltar, eles aparecerão na área geral em que deveriam estar. A exceção, é claro, é para qualquer NPC "inteligente" que, por algum motivo, precise permanecer no local em que foram quando o servidor caiu.
  • Além disso, um jogador não deve estar logado por muitas horas por vez (observe que aqui estou pensando em "voltar ao lobby" como logout). Eventualmente, eles precisarão fazer uma pausa no banheiro ou obter comida ou ser interrompidos pelos pais / amigo / o que quer ou dormir. Portanto, eles realmente não devem estar logados realisticamente sem parar por mais de, digamos, 8 horas, mesmo para os jogadores mais hardcore. Se um "jogador" estiver conectado por um período realmente longo, há uma boa chance de ser várias pessoas ou um bot, e nenhum deles ser desejável ou normal.
  • Além disso, seu processo de logout já deve estar checando itens como os comandos consecutivos acima mencionados. Essencialmente, ele já deveria estar empacotando o personagem, então é obviamente um horário nobre para despejá-lo no disco.

Pensamentos finais

  • Claramente, sou a favor da última abordagem, mas tentei ser imparcial em relação às três.
  • É difícil dizer qual dos dois primeiros métodos é mais inútil. Com o primeiro método, se o personagem enviar vários comandos de movimentação, eles serão salvos em disco e substituídos, quando claramente puderem ser agrupados em um. Mas com o segundo método, se você tiver metade da sua população por perto, suas posições serão salvas em disco, mesmo que sejam exatamente as mesmas desde a última operação de backup. No terceiro caso, é muito possível que alguém possa se conectar e se desconectar imediatamente, mas na maioria das vezes muitas coisas sobre o jogador mudaram, então o desperdício parece mínimo.
  • Lembre-se de que isso é inteiramente para backup em caso de falha, e uma falha deve ser absolutamente minimizada. É bom lidar com esse caso de exceção, mas, no final, se o servidor falhar, alguns dados serão perdidos e alguns jogadores ficarão chateados. Portanto, apenas implemente o método que puder, o que achar mais simples ou melhor, e continue.
  • Não confie nisto como o salvamento padrão; coloque um bom botão de desligamento no aplicativo do servidor, que normalmente fecha as conexões e grava tudo no banco de dados. Use isso normalmente.

Por fim, não tome esse conselho como verdade absoluta. Eu não escrevi um sistema de backup multiplayer. Eu estou trabalhando em um "jogo" on-line, que é por isso que eu ter pensado nisso e escreveu os meus pensamentos acima, mas eu não ter chegado ao estágio de aplicação do presente ainda. Portanto, isso é escrito sem experiência real, mas após muita leitura e coleta de conhecimento sobre o tópico.

Ricket
fonte
4
Pelo que observei pessoalmente, os MMOs comerciais usam uma combinação dos três. As gravações ocorrem após eventos e ações importantes, como abates / saques / negociações de chefes, periodicamente para impedir que ações não críticas sejam perdidas (e para não punir aqueles que estão logados por um longo período de tempo) e sempre ao sair. Um único método geralmente não é suficiente. Quase todos esses métodos dependem de um banco de dados de estilo SQL subjacente, que é copiado e restaurado de forma transparente, se houver um mau funcionamento do hardware.
NtscCobalt
@ NtscCobalt - eu estava com você até o "banco de dados estilo SQL". SQL é realmente um requisito? E o NoSQL?
beatgammit
@tjameson Bem, meu comentário foi escrito antes de eu tocar no NoSQL. Eu estava apenas tentando dizer que você não deve rolar seu próprio formato, mas mesmo assim eu recomendaria o SQL, pois você deve conhecer o esquema antes (ou seja preguiçoso e use o Entity-Key-Value) e a consistência é mais importante que o capacidade de particionar esses dados. Consulte stackoverflow.com/questions/7339374/… para obter mais informações.
NtscCobalt
1

Suponho que depende do tipo de jogo e da quantidade de tráfego entre jogadores e o servidor.

Em um MMORPG, não faria sentido salvar a posição dos jogadores toda vez que eles enviarem as informações ao servidor. Faria mais sentido atualizar quando os dados atuais do jogador estiverem "antigos", por assim dizer. Também pode ser benéfico salvar o estado do jogador em grandes eventos, como atravessar um novo território, derrotar um chefe ou sair de uma loja.

Em um jogo baseado em turnos, definitivamente faria sentido salvar o estado do jogador toda vez que eles terminam o turno, bem como após o turno do adversário (salvo perda de saúde, efeitos de feitiços, etc.).

Novamente, a resposta depende inteiramente da escala e dos recursos do seu servidor. Trata-se de encontrar o melhor equilíbrio e otimizar o máximo possível sem sacrificar a qualidade.

JMellow
fonte
1

Se sua única preocupação é quando eles saem, então uma resposta simples é salvar a posição deles quando ocorrerem quaisquer condições para eles que não existem mais no mundo do jogo (devido ao logoff ou desconexão).

Em uma observação lateral, eu ficaria um pouco desconfiado de o cliente relatar ao servidor sua posição ou, pelo menos, sem alguma forma de verificação de integridade do lado do servidor. Se você já tiver isso em prática, provavelmente poderá salvar essa posição ao fazer logoff ou desconectar, pois não precisa se preocupar em obter nenhum dado diretamente do cliente.

Lunin
fonte
Sim, daí a necessidade de enviar atualizações regulares para o servidor em valores como position e XP. Quanto mais tempo você deixa, mais discutível fica se o jogador realmente acumulou ou não os deltas relatados. Se você restringir esses períodos de "check-in", é muito mais fácil monitorar / controlar.
Engenheiro de
O problema de saber quando exatamente um jogador saiu de um jogo de navegador de longa duração não é realmente trivial.
Lanbo
Concordo que não é trivial, mas é um problema que você precisa resolver de uma maneira ou de outra na maioria dos jogos, mesmo que seja apenas para decidir quando o avatar deles não aparecerá mais. Feito isso, deve ser uma questão relativamente simples conectar-se a esse cenário e salvar sua última posição válida.
Lunin