Por que os jogos aparentemente recarregam o nível inteiro ao reiniciar um nível?

47

Os dados são realmente modificados tanto durante o jogo?

Estou assumindo que a longa pausa entre reiniciar um nível é o nível inteiro recarregado. Mas parece-me que um sistema bem implementado deve ser capaz de "pingar" de volta ao início do nível.

É mais perceptível em consoles, mas não é imperceptível em jogos para PC.

Malha
fonte
8
A resposta para isso depende muito do jogo, dos desenvolvedores, de seus hábitos e experiências e de muitos outros fatores. A única resposta correta em um nível geral seria: às vezes é modificado muito, às vezes não, às vezes o material é transmitido e, assim, o início não está na memória mais, e às vezes os jogos já fazer back "ping" para o início do nível, e jogos que às vezes não têm boas razões para que não possam fazê-lo e às vezes é apenas porque não foi implementado o suficiente.
Christian
4
De um modo geral, é muito mais fácil recarregar o nível (que coloca tudo em seu estado inicial), em vez de desfazer tudo o que o jogador fez. Esse é o caso da minha experiência de qualquer maneira.
Benjamin Danger Johnson
A questão não é em preto e branco. Quanto estado é recarregado? Muitos jogos recarregam conjuntos de texturas inteiros sem uma boa razão. Claro, indo de nível 5 para nível 6 pode significar carregar novas texturas, mas isso não significa que você deve fazer isso toda vez que você (re) começar o nível 6.
MSalters
@MSalters Será principalmente sobre o estado do jogo, e não sobre os recursos, talvez você não precise recarregar um texure de uso comum, mas sim o inimigo que você já matou - o objeto para ele precisa ser destruído e recarregado no estado inicial (mesmo se sua textura ainda estiver bem armazenada na memória.)
Tom 'Blue' Piddock
Acho que alguém jogou Wing Commander III em um sistema legado.
precisa

Respostas:

54

Bem, agora - que pergunta simples, mas interessante de resolver.

Ao recarregar um nível, há tantos fatores que precisam ser levados em consideração que a resposta pode ser de várias maneiras.

Se o seu estado de nível contiver uma grande lista de ativos, pode ser mais prático começar com uma lista limpa ao recarregar um nível para um estado de salvamento / missão, pois isso mantém o estado exato do nível ao recarregar, mas não é muito demorado. de processamento. No entanto, é mais eficiente redefinir os ativos sozinhos se houver apenas alguns a serem levados em consideração - garantindo que você possa reiniciar a ação rapidamente nesses níveis menores. O último é especialmente verdade quando você não precisa preservar nada na cena ou não é afetado por suas escolhas no jogo - se você não precisou de corpos para serem preservados desde a primeira corrida por uma vila, eles não precisa ser recarregado no caminho de volta a esse nível, economizando tempo do processador e economizando / tempo de acesso ao estado da missão.

Um bom exemplo para se pensar seria um atirador em primeira pessoa que usasse decalques de destruição de terreno / bala que tinham um estado persistente durante essa jogada, mas não permaneceriam se você reiniciasse esse ponto de verificação ou nível .

Se você fosse rebobinar o nível em vez de destruí-lo e recarregá-lo, teria que rastrear cada estado alterado. Se você fizesse um buraco na parede com um foguete, geraria pedaços de terreno a partir das peças que caem da parede, o modelo da parede mudaria para produzir o buraco e você teria efeitos de partículas que foram gerados para torná-la bonita . Para limpar isso, rebobinando-o novamente para um estado "reinicializável", você teria que:

  • Remova quaisquer gibs gerados dinamicamente para essa parede (mas não os do estado que você carregou)
  • Remova o efeito de partícula para a poeira do buraco de bala
  • Substitua / repare a parede para se livrar dos buracos que você criou
  • Redefinir a munição do jogador
  • Etc ...

Com tantos recursos a serem rastreados para rebobinar um nível, geralmente é menos intensivo em processador simplesmente destruir o nível inteiro e recarregar todos os ativos novamente em seus estados padrão ou específicos da missão. Ter que redefinir objetos específicos envolve pesquisar uma lista dos objetos na cena e acessar suas propriedades para redefini-los. Em vez de reparar o buraco de bala na parede limpando, você não precisa calcular nenhuma ação de limpeza, basta excluir todo o nível da memória e recarregá-lo do zero.

Isso significa que recarregar um nível é feito a partir de um objeto de estado (um arquivo de jogo salvo ou um script de missão) e não precisa de cálculos dinâmicos. Para os consoles, isso é exacerbado pelos tempos de carregamento envolvidos nos discos. Ele também ajuda os jogos para PC, pois pode levar em consideração computadores que não têm o poder de processamento para tornar aceitáveis ​​os tempos de carregamento.

Portanto, para grandes níveis de conteúdo - Carregar um único estado em vez de calcular e "rebobinar" um:

  • É menos intensivo em processador
  • É mais eficiente em máquinas de nível inferior
  • Permite que um script de missão e arquivo de salvamento sejam usados ​​da mesma maneira (potencialmente use o mesmo sistema de carregamento para carregar um estado de salvamento ou um estado de ponto de verificação de missão ao reiniciar o nível)
  • Significa que você tem menos trabalho como desenvolvedor para redefinir um nível - é muito mais fácil programar uma recarga completa dos dados da sessão do que rastrear e retroceder. Este é provavelmente o ponto mais influente

No entanto, como contra-exemplo, um jogo de luta (grande exemplo da vida real sendo Street Fighter 4) pode não precisar recarregar tantos recursos para reiniciar um nível. Os 2 jogadores, o estado do ambiente para o nível e os cronômetros de nível simples são na maioria estáticos e não dinâmicos (a saúde dos jogadores sempre reaparece em 100% a cada rodada, os cronômetros são redefinidos para 90 segundos e o nível não tem buracos de bala [ou faz!] ) e, portanto, redefinir o nível é uma questão de recuperar a saúde dos lutadores e colocar o ambiente de volta às suas posições originais (como espectadores em alguns níveis).

Portanto, para um jogo de luta ao fazer uma revanche (não passando de rodada para rodada), você precisa:

  • Redefina Saúde e energia para Máximo ou padrões (sempre o mesmo por personagem)
  • Reset Timer
  • Redefinir posições iniciais do personagem
  • Redefinir o terreno para o estado padrão (sem buracos de bala para consertar ou recarregar!)

E essa é a lista inteira essencialmente - o que significa que uma redefinição rápida do estado em vez de uma recarga de nível completo é mais viável. Isso também pode ser demonstrado pelo tempo de carregamento quando você inicia a partida. Demora muito tempo para carregar todos os modelos de personagens e níveis, mas apenas alguns processadores marcam para redefinir as posições iniciais dos personagens entre as correspondências com um modelo já carregado.

É importante observar que esse também é um requisito mais procurado dos jogos de luta, pois seus jogadores tendem a querer voltar à ação incrivelmente rápido, pois as partidas normalmente duram apenas um minuto - enfatizando que essa resposta depende muito do jogo e gênero. Os FPS exigem ativos mais dinâmicos, enquanto os Fighters exigem ações repetíveis rápidas.

Espero que isso tenha esclarecido sua pergunta.

Tom 'Blue' Piddock
fonte
7
Ótima resposta ... o lado cínico de mim, colocaria o seu: "menos trabalho para o ponto de desenvolvedores mais acima da lista ... mas talvez seja a implementação do mecanismo que poderia ser melhor."
Mesh
3
Além disso, e a recuperação de bugs? Um NPC não se move por causa de um bug no sistema físico, um vazamento de memória etc. Mesmo se o jogo for exaustivamente testado, essas coisas ainda acontecem e deve haver uma maneira de redefinir o jogo para um estado conhecido e funcional.
Sulthan
9
Menos trabalho é uma meta invejável a ser alcançada, não um assunto de vergonha. Você poderia passar uma semana para construir um sistema de enrolamento e um mês recebendo todos os erros fora, ou de recarga e pegue outros recursos =)
Patrick Hughes
1
Eu acho que o custo é o argumento mais importante aqui. A menos que recarregar um nível aconteça muito e se torne um grande aborrecimento para o usuário, não há incentivo para escrever código otimizado para acelerar o recarregamento. Custa apenas menos para reutilizar o código para uma carga normal.
21413 orlp
1
+1 Eu só quero esclarecer que recarregar um nível e carregar um nível - se o recarregamento jogar tudo fora e começar com um carregamento novo - não precisará ser escrito nenhum novo código para atingir o objetivo do jogo. Um sistema de rebobinagem é um conjunto de códigos completamente novo que não é trivial e, como depende de um estado variável, é extremamente difícil depurar. Exemplo: "Correção de bug: reiniciar um nível depois de colocar um capacete em cima de uma bomba depois que um míssil explode dentro de 200 pixels de água não causa mais um acidente na área de trabalho". Em suma, você teria que ter um bom motivo para se preocupar.
BrianH
14

Para esclarecer as respostas existentes da sua pergunta sobre consoles: elas não têm memória suficiente para armazenar o estado inicial e o estado atual para jogos complexos maiores.

Um jogo pode armazenar o nível e o estado inicial separadamente, para que apenas o estado possa ser recuperado, e é muito provável que muitos jogos o façam. Mesmo o streaming, mesmo assim, será um pouco mais lento do que se tivesse sido mantido na memória.

O "melhor" console de geração atual possui apenas 512 MB de memória compartilhada entre dados e gráficos da CPU. Isso é minúsculo. Uma das dores de cabeça atuais do desenvolvimento de console é tentar se encaixar em jogos que atendem aos níveis de qualidade atuais com quantidades tão pequenas de memória. A contagem de kilobytes pode se tornar importante, especialmente perto da data de envio. Armazenar uma cópia do estado inicial de um nível é uma quantidade de dados que podem ser feitos sem, permitindo que mais memória seja usada para coisas que tornam o jogo mais interessante durante o jogo, em vez de simplesmente acelerar o recarregamento do nível.

Idealmente, o jogador passa mais tempo jogando o jogo do que morrendo e reiniciando, portanto, otimizar para uma melhor experiência durante o jogo faz mais sentido.

As coisas podem mudar drasticamente com os consoles de última geração e seus 8 GB de memória. Ou eles podem permanecer iguais, com modelos e materiais simplesmente de alta resolução e grande número de objetos ativos no jogo. O tempo vai dizer. Dado que os jogos para PC normalmente têm como alvo máquinas com 2 GB de RAM e 512 MB de VRAM (embora muitos sejam dimensionados para valores muito maiores), os 8 GB dos novos consoles são bastante luxuosos no que diz respeito às linhas de base mínimas. Provavelmente, veremos uma transição para jogos que exigem CPU / OS de 64 bits e 4-8 GB de RAM com 1-2 GB de VRAM nos próximos anos. Armazenar vários estados na memória para obter instantâneos rápidos deve ser muito mais fácil.

Sean Middleditch
fonte
+1 Informações fantásticas e uma ótima explicação de por que os consoles são marcadamente mais lentos na recarga.
Tom 'Blue' Piddock
7

Eu discordo de grande parte da resposta de Blue, não acredito que exista um caso técnico para não redefinir níveis - certamente nunca encontrei um. A carga de nível é quase sempre mais lenta que a reposição de nível, na verdade acho difícil conceber uma ocasião em que não seria. Na maioria dos casos, os jogos podem oferecer carregamento de nível efetivamente instantâneo se os desenvolvedores escolherem.

A resposta real é, como sugerido, é mais fácil e rápido. O carregamento repetido de níveis é algo que um jogo exige de qualquer maneira; portanto, redirecionar isso para uma reinicialização de nível é relativamente direto. A redefinição requer novos caminhos complexos, com grande potencial para novos bugs e vazamentos de memória e requer um investimento decente de tempo do desenvolvedor. Em alguns casos, também pode aumentar os limites de memória. Como os jogos raramente são desenvolvidos com um tempo excedente de desenvolvedor, itens como redefinição de nível têm uma tendência lamentável a cair ao longo do caminho, principalmente se a arquitetura do jogo não for a melhor construída em primeiro lugar.

Embora eu suponha que alguém possa ter uma situação em que "rebobinar" seja necessário para redefinir, na verdade a maioria dos jogos precisa apenas armazenar o estado original, fornecer um meio eficaz para redefinir completamente esse estado para objetos retidos e um meio para sinalizar objetos para serem redefinidos. abandonar na redefinição. As informações do estado do jogo também precisam ser armazenadas e restauráveis. Esse tipo de informação geralmente é relativamente leve na memória, em comparação com os requisitos de um nível inteiro. Isso elimina a necessidade de carregamento lento e caro de dados do disco (incluindo itens grandes como texturas e modelos) e o substitui por uma rápida, -memória da cena.

Jack Aidley
fonte
3
Você pode querer verificar a resposta de Sean para um exemplo de um caso técnico, onde você pode querer recarregar um nível mais "redefinir"-lo
SpartanDonut
2

Para permitir grandes níveis ou jogabilidade uniforme, mesmo com memória limitada (a memória é sempre muito pequena, a questão é se você atingir o limite na RAM primeiro ou na placa gráfica), existe outra estratégia:

Tenha apenas a parte do nível na memória que o jogador precisa atualmente ou precisará em alguns segundos. Modelos, texturas, amostras de sons, ... que provavelmente não são mais necessários, são removidos da memória.

Dungeon Siege vem à mente (os desenvolvedores alegaram uma vez que o gerenciamento de memória consumia mais poder de processamento do que o jogo real); O nível (ou mesmo um ponto de reaparecimento 30 segundos atrás) pode não estar mais (completamente) na memória.

Geralmente, uma nova recarga é a maneira mais fácil, a mais barata e, talvez, a mais rápida.

Edit: Aqui está um artigo sobre os mecanismos de carregamento do Dungeon Siege: O Mundo Contínuo do Dungeon Siege

linac
fonte
Bom ponto, não pensei em níveis contínuos ou contínuos. Isso exigiria um sistema de carregamento de nível completamente diferente.
Tom 'Blue' Piddock
2

Com as excelentes respostas de Sean e Blue em relação às limitações da plataforma física e decisões pró-contras, vou expandir um comentário para uma abordagem diferente:

Por que você provavelmente deve recarregar completamente o nível

Então você tem sua chamada loadLevel () funcionando perfeitamente, yay! Você transmite informações de um arquivo nivelado e avança na construção do mundo com base nele, criando objetos e carregando texturas e sons à medida que avança. Então, quando tudo estiver pronto - ou pronto "o suficiente" para iniciar a reprodução, você chama startPlay () e seu mundo é revelado e sua música começa a tocar.

Agora, quando você terminar o nível, ou sair para o menu ou sair do jogo, chame unloadLevel () para liberar todos os recursos e memória que você estava segurando para permitir uma experiência suave.

Agora, o que acontece quando você deseja adicionar um recurso "Reiniciar nível"? Bem...

unloadLevel(currentLevel);
loadLevel(currentLevel);
startPlay();

E você está pronto! Não há código novo, apenas algumas chamadas simples de função, e você já escreveu e depurou tudo isso, agora seu novo recurso de reinicialização brilhante é riscado da sua lista e provavelmente nunca mais será encontrado novamente - código sem crueldade e sem ferrugem é o melhor tipo! Mova o código para uma função restartCurrentLevel () e você poderá dobrá-lo e nunca mais vê-lo - talvez depois de verificar se há um nível para reiniciar, é claro :)

Mas então você se pergunta se isso não é um desperdício, descarregando coisas que você está prestes a recarregar novamente de qualquer maneira. Bem, se seus níveis e recursos forem pequenos, o máximo que você terá a ganhar é alguns segundos de tempo de carregamento cada vez que "Reiniciar" é chamado mesmo em sistemas lentos (e talvez smartphones mais antigos), então quem se importa? "Otimização prematura", você tem coisas melhores para fazer com o seu tempo.

Ah, mas agora seus níveis estão aumentando e suas texturas estão ficando mais detalhadas e a trilha sonora foi cortada em 512kbps com canais separados para todas as camadas de voz e música (parecia uma boa ideia na época, embora você não se lembre do porquê. ..) e algo sobre "matrizes de transformadas de Fourier multidimensionais de rastreamento de raios voxel dependentes do estado" que você acha que são totalmente compostas e não uma coisa real, e a carga de nível realmente leva um tempo agora e seu começo a incomodá-lo. Você até testou com pessoas reais e elas demonstram uma aversão aos tempos de espera como algo pior do que jogos semelhantes (você não está esperando uma capital do MMORPG com 100 jogadores carregar totalmente em <2 segundos, não é?), e é um problema.

Então, como você otimiza? Bem, se a recarga de nível for um problema, o carregamento de nível não será um problema? Se você acha que está apenas recarregando, por que diabos as pessoas estão recarregando seu nível com muito mais frequência do que apenas carregam o nível? Parece um problema de jogo, não um problema de engenharia de código. Quem acha que é divertido recarregar um nível repetidas vezes e só deseja que seja mais rápido do que totalmente evitável ?

Corrija o problema real primeiro!

Mas digamos que seu jogo foi projetado para que você reinicie pelo menos ocasionalmente, e o tempo de carregamento é longo o suficiente para que seja possível executar uma vez e totalmente inevitável, mas você não deseja fazer isso novamente. Que tipo de jogo é esse, afinal? Parece um pouco de um problema estranho ... talvez um jogo de alta resolução do tipo Portal, onde se presume que você vai estragar o quebra-cabeça repetidamente?

Primeiro de tudo, você deve perceber que isso não será trivial. Você precisará escrever um código completamente novo e não testado, e é "dependente do estado" para que você nem saiba o que é ou não será reutilizado entre as jogadas niveladas. Existem elementos aleatórios, spawns, texturas variáveis ​​(seus esqueletos às vezes usam armaduras?) Ou outros elementos variáveis ​​no seu nível? Existem coisas que variam com o jogador, como uma roupa ou modelo personalizado ou cores / portas / armadilhas?

Você fará comparações e muitas delas. Você percorrerá os elementos de nível, comparando o que será necessário e o que está carregado no momento (o que você faz com as coisas que foram carregadas para o último nível, mas não para este - libere-as ou segure-as para impedir um futuro carga?). Se isso é realmente um grande problema para o seu jogo, você provavelmente desejará alterar seu código de carga / descarga para ver se algo já está carregado antes de carregá-lo (tornando o código multiuso, mas potencialmente introduzindo novos bugs nos recursos e funções que funcionavam anteriormente) que libere cuidadosamente os recursos que não serão utilizados em um futuro próximo). Suspiro.

Não importa o que você faça, mesmo que seu jogo seja simples, você encontrará bugs obscuros que são baseados no nível / estado do jogador quando um nível foi reiniciado que não acontece quando você carrega o nível pela primeira vez. Então você pode escrever atualizações de jogos com texto como:

"Colocar um capacete em uma bomba em um ladrilho que explodiu com um míssil próximo a 200 pixels de água não corromperá mais os dados do jogo nem fará com que ele caia".

A verdadeira razão pela qual a maioria dos jogos não se incomoda

Você já reparou que a maioria das pessoas apenas pinta ou drywall sobre as paredes existentes, em vez de descascar até uma camada de base, ou coloca o tapete em cima de pisos de madeira em vez de puxá-los para cima?

O fato simples é que é mais trabalho para recompensa mínima. Pintar sobre as paredes existentes funciona bem na maioria das vezes , e o valor de rasgar pisos de madeira é geralmente mínimo ou inexistente.

O mesmo acontece com o software, desde jogos a apresentações em Power Point multimídia - se tudo o que você faz é tirar alguns segundos da tela de carregamento, as pessoas passam 1% do tempo olhando, então é melhor que seja incrivelmente trivial ou você está conseguindo um retorno muito ruim do seu tempo investido.

E, portanto, a maioria dos jogos não se incomoda, e eu tenho problemas para pensar em muitos jogos em que o carregamento de telas fez com que um jogo de outro modo valesse menos a pena, exceto alguns exemplos extremos; os exemplos extremos são onde a otimização para carregamento de nível mais rápido faz sentido, e isso é uma pequena fração de jogos que chega ao público, e provavelmente até mesmo uma fração menor de jogos que ninguém vê porque nunca é lançado.

BrianH
fonte
0

Porque é mais difícil desenvolver o comportamento oposto, que consiste em manter os dados estáticos do jogo (como texturas, informações geológicas, mobs não afetados) na memória e recarregar apenas os dados dinâmicos (como posição do jogador, estatísticas do jogador, status da missão, inventário) .

Como custa mais dinheiro e tempo, os desenvolvedores de jogos geralmente não fazem isso.

Xtro
fonte
Isso não cobre as situações em que o oposto deve ocorrer devido ao gênero do jogo ou às demandas individuais. Como o Prince of Persia, que precisa gravar o estado do jogo para usar uma mecânica de jogo específica e os exemplos de jogos de luta que eu dei, precisam ser capazes de recarregar estados individuais de item / nível / personagem para reiniciar no meio da partida a próxima rodada ou reinicie a partida para iniciar o próximo jogo. Eles são necessários para atender às demandas do jogo em questão e, portanto, é necessário que os desenvolvedores gastem mais tempo e dinheiro.
Tom 'Blue' Piddock
Se o oposto ocorrer em um jogo específico, a pergunta acima é inválida para esse jogo. . Porque o tempo de carregamento será mais rápido no jogo que o oposto ocorre em eu só respondeu a pergunta para a situação que se aplica a (que é os jogos que cargas patamar a partir do zero)
Xtro
Se o oposto ocorre onde a premissa da pergunta poderia ter acontecido, sempre vale a pena notar e por quê. Perder informações ou deixar de fora detalhes sobre por que uma situação ou solução surgiu nunca é benéfico. Dizer que não há necessidade de detalhes é um pouco contra-intuitivo, pois não haveria uma pergunta em primeiro lugar se a pessoa não estivesse buscando detalhes. Se você for capaz de fornecer mais detalhes, sempre se esforce para fazê-lo, pois isso ajudará outras pessoas a aprender mais sobre um assunto como um todo e a atender às necessidades do dia a dia.
Tom 'Blue' Piddock
então, sua reação é pela minha primeira linha de resposta, que é sobre "não há necessidade de detalhes", certo? se eu remover essa linha, você levaria -1 ponto de volta?
Xtro
Curiosamente - sim. Nunca desestimule os detalhes onde é possível fornecê-los e, geralmente, você descobrirá que suas respostas são muito mais apreciadas.
O que você quer tocar hoje