(Você pode querer saber sobre o termo "remendo de macaco" ou "soco de pato" por nada além da imagem mental bem-humorada.)
Além disso: se seu objetivo é diminuir o tempo de iteração para alterações no "comportamento", tente algumas abordagens que o levem ao longo do caminho e combine bem para permitir mais disso no futuro.
(Isso sairá um pouco tangente, mas eu prometo que retorne!)
- Comece com dados e comece com pequenos: recarregue nos limites ("níveis" ou similares) e, em seguida, use a funcionalidade do SO para obter notificações de alteração de arquivo ou simplesmente pesquisar regularmente.
- (Para obter pontos de bônus e tempos de carregamento mais baixos (novamente, diminuindo o tempo de iteração), consulte o processo de cozimento de dados .)
- Scripts são dados e permitem iterar o comportamento. Se você usa uma linguagem de script, agora tem as notificações / capacidade de recarregar esses scripts, interpretados ou compilados. Você também pode conectar seu intérprete a um console do jogo, a um soquete de rede ou similar para aumentar a flexibilidade do tempo de execução.
- O código também pode ser dados : seu compilador pode suportar sobreposições , bibliotecas compartilhadas, DLLs ou similares. Agora você pode escolher um momento "seguro" para descarregar e recarregar uma sobreposição ou DLL, manual ou automática. As outras respostas entram em detalhes aqui. Observe que algumas variantes disso podem interferir na verificação de assinatura criptográfica, no NX (sem execução) ou em mecanismos de segurança semelhantes.
- Considere um sistema profundo de salvamento / carregamento com versão . Se você pode salvar e restaurar seu estado de maneira robusta, mesmo diante das alterações de código, pode encerrar o jogo e reiniciá-lo com uma nova lógica no mesmo ponto. É mais fácil falar do que fazer, mas é factível e é notavelmente mais fácil e mais portátil do que mexer na memória para alterar as instruções.
- Dependendo da estrutura e do determinismo do seu jogo, você poderá gravar e reproduzir . Se essa gravação tiver apenas "comandos do jogo" (pense em um jogo de cartas, por exemplo), você poderá alterar todo o código de renderização desejado e reproduzir a gravação novamente para ver suas alterações. Para alguns jogos, isso é tão "fácil" quanto gravar alguns parâmetros iniciais (por exemplo, uma semente aleatória) e depois as ações do usuário. Para alguns, é muito mais complicado.
- Faça esforços para reduzir o tempo de compilação . Em combinação com os sistemas de salvar / carregar ou gravar / reproduzir acima mencionados, ou mesmo com sobreposições ou DLLs, isso pode diminuir sua recuperação mais do que qualquer outra coisa.
Muitos desses pontos são benéficos, mesmo se você não conseguir recarregar dados ou códigos.
Anedotas de suporte:
Em um PC RTS grande (equipe de aproximadamente 120 pessoas, principalmente C ++), havia um sistema de economia de estado incrivelmente profundo, usado para pelo menos três propósitos:
- Um salvamento "superficial" foi alimentado não ao disco, mas a um mecanismo de CRC para garantir que os jogos multiplayer permanecessem na simulação de etapa de bloqueio, um CRC a cada 10 a 30 quadros; isso garantiu que ninguém estava trapaceando e pegou bugs de dessincronização alguns quadros depois
- Se e quando ocorreu um erro de dessincronização para vários jogadores, um salvamento extra-profundo era executado a cada quadro e alimentado novamente ao mecanismo CRC, mas desta vez o mecanismo CRC geraria muitos CRCs, cada um para lotes menores de bytes. Dessa maneira, poderia dizer exatamente qual parte do estado havia começado a divergir no último quadro. Percebemos uma desagradável diferença no "modo de ponto flutuante padrão" entre os processadores AMD e Intel usando isso.
- Um salvamento em profundidade normal pode não salvar, por exemplo, o quadro exato de animação que sua unidade estava reproduzindo, mas obteria a posição, a saúde etc. de todas as suas unidades, permitindo salvar e retomar a qualquer momento durante o jogo.
Desde então, usei registro / reprodução determinística em um jogo de cartas em C ++ e Lua para o DS. Nós nos conectamos à API que projetamos para a IA (no lado C ++) e registramos todas as ações do usuário e da IA. Usamos essa funcionalidade no jogo (para fornecer uma repetição para o jogador), mas também para diagnosticar problemas: quando houve uma falha ou comportamento estranho, tudo o que precisávamos era pegar o arquivo salvo e reproduzi-lo em uma compilação de depuração.
Desde então, também usei sobreposições mais de algumas vezes, e o combinamos com o nosso sistema "cria automaticamente este diretório e carrega novo conteúdo no computador de mão". Tudo o que precisamos fazer é deixar a cena / nível / o que quer que seja e voltar e não apenas os novos dados (sprites, layout de nível etc.) carregariam, mas também qualquer novo código na sobreposição. Infelizmente, isso está ficando muito mais difícil com os computadores de mão mais recentes, devido à proteção contra cópias e mecanismos anti-hacking que tratam o código especialmente. Ainda o fazemos para scripts lua.
Por último, mas não menos importante: você pode (e eu tenho, em várias circunstâncias específicas muito pequenas) dar um soco no pato, remendando diretamente os códigos de instrução das instruções. Porém, isso funciona melhor se você estiver em uma plataforma e compilador fixos, e porque é quase impossível de manter, muito propenso a erros e limitado no que você pode realizar rapidamente, na maioria das vezes só o uso para redirecionar o código durante a depuração. Ele faz ensinar-lhe um inferno de um monte sobre o seu conjunto de instruções com pressa, no entanto.