Identificando ativos em um mecanismo de jogo?

12

Quero identificar meus ativos carregados, mas não sei qual deles devo escolher. Existem 2 opções:

  • Nome (sequência)

    • Este é o mais fácil e rápido com unordered_map (O (1)), mas muito mais lento do que usando números inteiros.
    • Facilmente compreensível no código.
  • Inteiros

    • O mais rápido.
    • Não são compreensíveis no código.

Eu sei que as seqüências de caracteres não são tão seguras ou rápidas, mas é tão ruim ou conta apenas como ruim em um título AAA? Eu poderia criar enumerações para usar números inteiros, mas se eu carregar a cena, os ativos etc. de um arquivo em tempo de execução, não posso usar enumerações. Existe uma maneira de tornar esses inteiros legíveis se forem gerados em tempo de execução?

Sei que esse problema tem alguns tópicos por toda a Internet, mas não consegui descobrir o quão importante é esse caso.

Tudvari
fonte
10
Por que não uma implementação de ambos? A versão da string se conecta a um Dictionary <string, int> que, por sua vez, chama um Dictionary <int, Asset>. Você pode contornar a camada baseada em string no código, mas use a camada baseada em string para interação do usuário.
Krythic
2
Eu entendo o ponto de Krythic. Se seu código gosta de números inteiros por velocidade, deixe seu código usar números inteiros. Se seus usuários gostarem de strings por legibilidade, permita que eles usem strings. Os dois podem coexistir muito feliz (e você pode compilar seletivamente a versão string em desenvolvimento constrói somente, se você quiser pular a sobrecarga inteiramente em release)
DMGregory
Mesmo problema em um contexto um pouco diferente: Diferentes métodos de implementação de itens - quais são as diferenças?
Philipp

Respostas:

19

Você pode suportar ambos.

Embora seja muitas vezes mais eficiente em tempo de execução para o ativo de referência por um número inteiro ou alguma tecla fast-to-compare semelhante, muitas vezes é mais eficiente em tempo de design para referenciá-los pelo nome, porque os seres humanos são muito melhores em trabalhar com nomes como enemy_bullet_casing_soundque 72910613.

Use uma chave inteira para procurar diretamente os recursos e use esse número inteiro no código sempre que possível (onde você pode colocar o valor real do número inteiro em uma variável e, assim, trabalhar com ele mais facilmente). Forneça um mapeamento do nome para essa chave inteira (em vez de diretamente para o recurso) e use esse mapeamento sempre que encontrar referências nomeadas a ativos para resolver a chave inteira real e encontrar o ativo.

O uso da pesquisa baseada em nome tornará seus arquivos de dados muito mais fáceis de trabalhar e o mapeamento do nome para uma chave mais rápida preservará todos os benefícios importantes de uma chave do tipo inteiro mais rápida, em qualquer lugar que seja necessário.


fonte
Meu caso: quero alterar o material de um objeto, por isso envio uma solicitação com o nome do novo material. (string) Em seguida, no sistema gráfico, há uma pesquisa em um mapa não ordenado <string, ponteiro>, e o ponteiro do material do objeto será substituído pelo novo ponteiro. Então, no meu caso, não preciso convertê-lo em um número inteiro? (porque eu convertê-lo para ponteiro e nas algorhytms freqüentes que usam ponteiros, eu só usar cordas para as coisas ocasionais.)
Tudvari
Ou devo usar IDs inteiros em vez de ponteiros em todos os lugares possíveis? (Portanto, não preciso incluir o arquivo de cabeçalho, por exemplo, o material.) Por exemplo, o componente renderizador agora armazena o ponteiro do material usado, que pode ser usado diretamente pelo mecanismo gráfico, mas preciso incluir Material.h . Mas quando armazeno apenas números inteiros no componente renderizador, não preciso incluir Material.h, mas preciso fazer uma pesquisa baseada em números inteiros na matriz de ponteiros. Eu acho que o último é melhor. É isso? Devo refatorar isso?
Tudvari
1

No meu projeto, uso seqüências de caracteres hash, que são transformadas, em tempo de compilação, em números únicos (desejo!). Então, quando eu preciso de um recurso, por exemplo, uma textura que eu simplesmente chamo

MngTexture->get(hash("my_texture"))

E como estou criando uma estrutura de sistema de entidade simples e preciso carregar dados de componentes de arquivos, criei uma linguagem simples como json para armazenar dados, mas é compilável (transformando palavras e caracteres de dígitos em números e de strings em valores de hash) . Então, por exemplo, se eu quiser vincular a textura com o hash de ID ("my_texture") para "ball.PNG" no meu arquivo de dados, terei

|my_texture| = "ball.PNG"

Onde || é um operador que diz ao compilador para hash a palavra dentro.

Então, basicamente, eu uso seqüências de caracteres que são mapeadas para ints em tempo de compilação (para que elas não tenham sobrecarga), tanto no código real quanto nos arquivos que são os fluxos para carregar componentes. Para calcular o hash em um tempo de compilação, basta pesquisar no Google, uma função simples de 5 a 10 linhas de código.

É claro que você pode carregar a string dos seus arquivos e hash em tempo de execução; nesse caso, você não precisa escrever o dicionário por conta própria porque o algoritmo fará isso por você (criando números inteiros a partir das strings) e eu acho que o hasing é pelo menos tão rápido quanto procurar em um mapa, devido à localização da memória (você está apenas percorrendo uma string com poucos bytes de comprimento).

Espero que isso possa ajudar.

Liuka
fonte
0

Identificar objetos por seqüências de caracteres não é o ideal, ints são muito mais eficientes. Por conveniência, você pode manter uma tabela (ou dicionário) de cadeias de caracteres em ints para ajudar no tempo de design e durante a depuração.

Eu recomendaria, no entanto, que dentro do código do seu jogo principal você se refira apenas aos objetos pelo ID inteiro (ou uma enumeração para facilitar a leitura). Isso facilita a divisão da tabela de cadeias como um ativo separado. Se o código do jogo principal não se basear nessa tabela de strings, você poderá removê-lo do jogo lançado, economizando uma quantidade significativa de memória - uma consideração importante se estiver trabalhando em um jogo para celular e quiser manter os tamanhos de download tão pequenos quanto possível.

steeveeet
fonte