Pergunta

Não programo jogos há cerca de 10 anos (minha última experiência foi DJGPP + Allegro), mas pensei em dar uma olhada no XNA no fim de semana para ver como estava indo.

Estou bastante impressionado, mas à medida que continuo a montar um mecanismo de jogo, tenho uma pergunta (provavelmente) básica.

Quanto você deve confiar nos delegados e eventos do C# para conduzir o jogo?Como programador de aplicativos, uso muito delegados e eventos, mas não sei se há uma sobrecarga significativa para fazer isso.

No meu mecanismo de jogo, projetei uma espécie de "câmera de perseguição", que pode ser anexada a um objeto e então recalcular sua posição em relação ao objeto.Quando o objeto se move, existem duas maneiras de atualizar a câmera de perseguição.

  • Tenha um método "UpdateCameras()" no loop principal do jogo.
  • Use um manipulador de eventos e faça com que a câmera de perseguição se inscreva em object.OnMoved.

Estou usando o último, porque me permite encadear eventos e automatizar muito bem grandes partes do mecanismo.De repente, o que seria enorme e complexo caiu para um punhado de manipuladores de eventos de 3 a 5 linhas... É uma beleza.

No entanto, se os manipuladores de eventos disparados a cada nanossegundo se revelarem uma grande desaceleração, irei removê-los e seguirei a abordagem de loop.

Ideias?

Foi útil?

Solução

Se você pensasse em um evento como uma lista de assinantes, em seu código tudo o que você faria seria registrar um assinante.O número de instruções necessárias para conseguir isso provavelmente será mínimo no nível CLR.

Se você deseja que seu código seja genérico ou dinâmico, será necessário verificar se algo está inscrito antes de chamar um evento.O mecanismo de evento/delegado de C# e .NET fornece isso a um custo muito baixo (em termos de CPU).

Se você estiver realmente preocupado com cada ciclo de clock, nunca escreveria uma lógica de jogo genérica/dinâmica.É uma troca entre código sustentável/configurável e velocidade total.

Bem escrito, eu preferiria eventos/delegados até poder provar que isso é um problema.

A única maneira de saber realmente se isso é um problema para você é traçando o perfil do seu código - o que você deve fazer de qualquer maneira para qualquer desenvolvimento de jogo!

Outras dicas

É importante perceber que os eventos em C# não são eventos assíncronos enfileirados (como, por exemplo, a fila de mensagens do Windows).Eles são essencialmente uma lista de ponteiros de função.Portanto, gerar um evento não tem implicações de desempenho piores do que iterar uma lista de ponteiros de função e chamar cada um deles.

Ao mesmo tempo, perceba que por causa disso os eventos são síncronos.Se o seu evento ouvinte for lento, você atrasará a aula subindo os eventos.

A questão principal aqui parece ser:"Qual é a sobrecarga associada ao uso de delegados e eventos C#?"

Os eventos têm pouca sobrecarga significativa em comparação com uma chamada de função normal.

O uso de Delegados pode criar lixo implícito e, portanto, oculto.O lixo pode ser uma das principais causas de problemas de desempenho, especialmente no XBox360.

O código a seguir gera cerca de 2.000 bytes de lixo por segundo (a 60 fps) na forma de objetos EntityVisitor:

    private delegate void SpacialItemVisitor(ISpacialItem item);

    protected override void Update(GameTime gameTime)
    {
        m_quadTree.Visit(ref explosionCircle, ApplyExplosionEffects);
    }

    private void ApplyExplosionEffects(ISpacialItem item)
    {
    }

Contanto que você evite gerar lixo, os delegados serão rápidos o suficiente para a maioria das finalidades.Por causa dos perigos ocultos, prefiro evitá-los e usar interfaces.

No meu tempo extra longe do trabalho real, também tenho aprendido XNA.

IMHO (ou não tão humilde se você perguntar aos meus colegas de trabalho) é que a sobrecarga dos manipuladores de eventos será sobrecarregada por outros elementos do jogo, como a renderização.Dado o uso intenso de eventos na programação .Net normal, eu diria que o código subjacente está bem otimizado.

Para ser honesto, acho que adotar um método UpdateCameras pode ser uma otimização prematura.O sistema de eventos provavelmente tem mais usos além da câmera.

O XNA incentiva o uso de interfaces, eventos e delegados para conduzir algo escrito com ele.Dê uma olhada nas classes relacionadas ao GameComponent que configuram isso para você.

A resposta é: “Tanto quanto você se sentir confortável”.

Para elaborar um pouco, se, por exemplo, você pegar e herdar da classe gamecomponent para uma classe cameracontroller e adicioná-la à coleção Game.Component.Então você pode criar suas classes de câmera e adicioná-las ao seu controlador de câmera.

Fazer isso fará com que o controlador da câmera seja chamado regularmente e seja capaz de selecionar e ativar a câmera adequada ou várias câmeras, se for isso que você deseja.

Aqui está um exemplo disso (todos os seus tutoriais são excelentes):ReoCode

Como um aparte, você pode estar interessado em saber que Shawn Hargreaves, desenvolvedor original de Alegro, é um dos principais desenvolvedores da equipe XNA :-)

Antes de abordar qual é o impacto de um evento em termos de desempenho, você deve primeiro avaliar se ele é ou não necessário.

Supondo que você esteja realmente tentando manter uma câmera de perseguição atualizada e não seja apenas um exemplo, o que você está procurando não é um evento (embora os eventos também possam funcionar), se você estiver seguindo um avatar, provavelmente será movendo-se na maior parte do tempo.

Uma abordagem que achei extremamente eficaz é usar transformações hierárquicas. Se você implementar isso de forma eficiente, a câmera não será o único objeto a se beneficiar de tal sistema, o objetivo seria manter a câmera dentro do espaço de coordenadas do objeto que ela está. monitorando.

Essa abordagem não é a melhor se você deseja aplicar alguma elasticidade à velocidade e à forma como a câmera rastreia o objeto, para isso, é melhor usar uma chamada de atualização, uma referência e um pouco de física básica de aceleração e resistência.

Os eventos são mais úteis para coisas que acontecem apenas de tempos em tempos ou que afetam muitos aspectos diferentes do aplicativo, como a morte de um personagem, provavelmente muitos sistemas diferentes gostariam de estar cientes de tal evento, estatísticas de mortes, a IA de controle e assim por diante, nesse caso, acompanhar todos os objetos que seriam necessários para verificar constantemente se isso aconteceu é muito menos eficaz do que lançar um evento e fazer com que todos os objetos interessados ​​sejam notificados apenas quando isso acontecer.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top