Depende do escopo do seu jogo. Um gerente de ativos é absolutamente essencial para títulos maiores, menos para jogos menores.
Para títulos maiores, você precisa gerenciar problemas como os seguintes:
- Recursos compartilhados - essa textura de tijolos está sendo usada por vários modelos?
- Duração do ativo - esse ativo que você carregou há 15 minutos não é mais necessário? Referência contando seus ativos para garantir que você saiba quando algo termina, etc.
- No DirectX 9, se certos tipos de ativos são carregados e seu dispositivo gráfico é "perdido" (isso acontece se você pressionar Ctrl + Alt + Del, entre outras coisas) - seu jogo precisará recriá-los
- Carregando ativos antes de precisar deles - você não poderia criar grandes jogos de mundo aberto sem isso
- Ativos de carregamento em massa - geralmente empacotamos muitos ativos em um único arquivo para melhorar o tempo de carregamento - procurar em torno do disco consome muito tempo
Para títulos menores, essas coisas são menos problemáticas, estruturas como o XNA possuem gerenciadores de ativos - há muito pouco sentido em reinventá-lo.
Se você precisar de um gerente de ativos, não há realmente uma solução única, mas descobri que um mapa de hash com a chave como hash * do nome do arquivo (abaixados e os separadores todos 'fixos') funciona bem para os projetos em que trabalhei.
Geralmente, não é aconselhável codificar nomes de arquivos em seu aplicativo, geralmente é melhor ter outro formato de dados (como xml) que represente nomes de arquivos como 'IDs'.
- Como uma observação lateral divertida, você normalmente recebe uma colisão de hash por projeto.
(Tentando evitar a discussão "não use um gerente de ativos" aqui, já que considero offtopic.)
Um mapa de chave / valor é uma abordagem muito útil.
Temos uma implementação do ResourceManager em que Fábricas para diferentes tipos de Recursos podem se registrar.
O método "getResource" usa modelos para encontrar o Factory correto para o tipo de recurso desejado e retorna um ResourceHandle específico (novamente usando o modelo para retornar um SpecificResourceHandle).
Os recursos são recontados pelo ResourceManager (dentro do ResourceHandle) e liberados quando não são mais necessários.
O primeiro complemento que escrevemos foi o método "reload (XYZ)", que permite alterar recursos de fora do mecanismo em execução sem alterar nenhum código ou recarregar o jogo. (Isso é essencial quando os artistas trabalham em consoles;))
Na maioria das vezes, temos apenas uma instância do ResourceManager, mas às vezes criamos uma nova instância apenas para um nível ou um mapa. Dessa forma, podemos simplesmente chamar "shutdown" no levelResourceManager e garantir que nada esteja vazando.
exemplo (breve)
fonte
As classes de gerente dedicado quase nunca são a ferramenta de engenharia certa. Se você precisar do ativo apenas uma vez (como um plano de fundo ou mapa), solicite-o apenas uma vez e deixe que ele morra normalmente quando terminar. Se você precisar armazenar em cache um tipo específico de objeto, use uma fábrica que primeiro verifique um cache e carregue algo, coloque-o no cache e o retorne - e essa fábrica pode ser apenas uma função estática acessando uma variável estática , não um tipo próprio.
Steve Yegge (entre muitos, muitos outros) escreveu uma boa história sobre como as classes inúteis de gerente, por meio do padrão singleton, acabam sendo. http://sites.google.com/site/steveyegge2/singleton-considered-stupid
fonte
Sempre achei que um bom gerente de ativos deveria ter vários modos de operação. Esses modos provavelmente seriam módulos de origem separados, aderindo a uma interface comum. Os dois modos básicos de operação seriam:
Você precisaria de uma ferramenta que possa obter todos os testes do banco de dados compartilhado e criar o conjunto de dados de produção.
Nos meus anos como desenvolvedor, nunca vi nada assim, embora tenha trabalhado apenas para um punhado de empresas, portanto minha visão não é realmente representativa.
Atualizar
OK, alguns votos negativos. Vou expandir esse design.
Primeiro, você realmente não precisa de aulas de fábrica, porque se você tem:
você conhece o tipo, então faça:
mas o que eu estava tentando dizer acima é que você não usaria nomes de arquivos explícitos, a textura a ser carregada seria especificada pelo modelo em que a textura é usada, para que você não precise realmente de um nome legível por humanos, poderia ser um valor inteiro de 32 bits, que é muito mais fácil para a CPU manipular. Portanto, no construtor para TextureHandle, você teria:
O AssetStream usa o parâmetro resource_id para encontrar a localização dos dados. A maneira como isso foi feito depende do ambiente em que você está executando:
Em desenvolvimento: o fluxo consulta o ID em um banco de dados (usando SQL, por exemplo) para obter um nome de arquivo e, em seguida, abre o arquivo, o arquivo pode ser armazenado em cache localmente ou extraído de um servidor se o arquivo local não existir ou for desatualizado.
Na liberação: o fluxo consulta o ID em uma tabela de chave / valor para obter um deslocamento / tamanho em um arquivo grande e compactado (como o arquivo WAD do Doom).
fonte
O que eu gosto de fazer por ativos é configurar um gerenciador fixo . Inspirados no mecanismo Doom, os grumos são pedaços de dados que contêm ativos, armazenados em um arquivo fixo que declara nomes, comprimentos, tipo (tamanho de bitmap, som, sombreador etc.) e tipo de conteúdo (arquivo, outro tamanho fixo, interno) o próprio arquivo fixo). Na inicialização, esses agrupamentos são inseridos em uma árvore binária, mas ainda não foram carregados. Cada mapa (que também é um agrupamento) possui uma lista de dependências, que são simplesmente os nomes dos agrupamentos que o mapa precisa para funcionar. Esses pedaços, a menos que já tenham sido carregados, são carregados no momento em que o mapa é carregado. Além disso, os blocos dos mapas adjacentes do mapa são carregados, não apenas ao mesmo tempo, mas quando o mecanismo está ocioso por algum motivo. Isso pode tornar os mapas perfeitos e não há tela de carregamento.
Meu método é perfeito para mapas de mundo aberto, mas um jogo baseado em níveis não se beneficiará da uniformidade que esse método proporciona. Espero que isto ajude!
fonte