Como as árvores de diálogo funcionam?

20

Ou seja, o que está conectado ao que e como se mover entre as linhas de fala quando uma subconversão termina?

Se você tiver exemplos de uma árvore de diálogo básica em C #, poste-os.

user1306322
fonte
Eu acho que seria ótimo ter dialog-treetag.
user1306322
Solicitar amostras de código geralmente não é encarado favoravelmente.
MichaelHouse
Se existem alguns exemplos de código da árvore de diálogo 101 que valem a pena compartilhar, isso não poderia prejudicar.
user1306322
O problema é que este site trata de obter respostas corretas para as perguntas. Não é para coletar amostras de código.
MichaelHouse
É por isso que a frase começa com "se". Mas o que estou pedindo é a explicação de como as linhas de diálogo se conectam entre si de uma maneira que possa ser traduzida eficientemente em código. Afinal, eu vou escrever em C #.
user1306322

Respostas:

24

O nome "árvore de diálogo" é um pouco enganador - eles geralmente são gráficos direcionados simples , não apenas árvores . A estrutura básica de dados desses gráficos geralmente consiste em algum tipo de "dados" para os nós, que representam os pontos em que estamos na conversa e os vincula a outros nós, que representam o que está sendo dito e feito pelos participantes e, opcionalmente, têm condições para limitar sua visibilidade ou scripts para executar várias ações adicionais. Geralmente, um dos nós é o nó inicial padrão (rótulos típicos para "ROOT", "START" e "GREETING") e nós que não têm links válidos a partir deles encerram a conversa.

Na maioria dos casos, o gráfico é representado na memória como uma lista de Nodeestruturas de dados, cada uma tendo pelo menos um ID e uma lista de 0..n Linkestruturas de dados. A lista pode ser local para o NPC ou global; o segundo caso é o preferido se você tiver muitos NPCs genéricos com os quais se pode conversar para obter informações, mas não ofereça conversas específicas por conta própria. O próprio sistema encontra o nó de conversa inicial do NPC, lembra seu ID como o atual, apresenta os links válidos atualmente para o jogador escolher (ou "[encerrar a conversa]" se não houver links válidos) e aguarda entrada. Quando o jogador escolhe um link, as linhas de diálogo associadas são exibidas e todos os scripts associados são executados.

Em vez de ter regras e condições complexas nos links, você pode conviver com uma variável booleana "válida" simples, que pode ser alterada a partir dos scripts de outros links de conversa (incluindo o padrão do nó inicial) ou por fora mecanismos. Em geral, essa abordagem é mais simples, mas adequada apenas para jogos com muito poucas conversas, uma vez que move a lógica de "Quando essa resposta é possível?" longe dos próprios dados de resposta.


Observe que a estrutura que descrevo aqui é um pouco diferente da do Byte56, pois os nós não precisam ter nenhuma linha de diálogo; os links podem ter todos eles. Na variante mais básica, isso se traduz na seguinte estrutura.

insira a descrição da imagem aqui

Martin Sojka
fonte
+1 Para mencionar regras e condições nos links, um gráfico direcionado simples geralmente não é suficiente e as coisas podem se complicar quando você começa a precisar delas.
Laurent Couvidou
+1 Gosto mais dessa estrutura. No entanto, eu não recomendaria isso como primeira passagem. Eu começaria com algo mais simples. Certamente é um alvo melhor para o qual atirar.
MichaelHouse
+1 Para uma resposta muito detalhada. Isso pode ser útil para mim mais tarde.
Marton
Essa imagem foi muito útil para mim, mas tenho que me perguntar por que o DialogueLine é separado do link? Cada link não teria seu próprio texto de resposta? E para onde iria o texto do NPC? Não faria sentido tê-lo no nó?
Kyle Baran
@Danjen Nesta estrutura, um Link pode ter vários DialogueLines, possivelmente de caracteres diferentes, até a próxima opção de diálogo aparecer. É também para onde o texto do NPC vai. Quando as linhas se repetem, diferentes Links podem compartilhar DialogueLines, possivelmente reordenando-os em sua lista (Vector), substituindo partes deles por linhas diferentes, adicionando interjeições e assim por diante.
Martin Sojka
16

As árvores de diálogo são criadas com uma estrutura de gráfico direcionada .

insira a descrição da imagem aqui

O gráfico é percorrido com base nas decisões de diálogo que o jogador toma. As opções de diálogo fornecidas ao usuário vêm das bordas que definem os caminhos para outros nós da caixa de diálogo.

Os gráficos direcionados são uma estrutura básica de dados. Eles podem ser facilmente implementados e você provavelmente desejará implementá-lo. Como você deseja adaptar o gráfico às suas necessidades de diálogo.

Alguns dos nós podem precisar ter condições especiais atendidas para aparecer. Por exemplo, o jogador exigiria uma habilidade na fala acima de X. Ou o jogador precisa ter completado a missão Z antes de poder avançar um ramo do diálogo. Ou eles precisam perguntar algo 4 vezes antes que o NPC discuta isso com eles. Esses recursos serão personalizados para o seu jogo. Mas vale a pena mencionar quando você estiver implementando o nó e a travessia de borda. Claro que é sempre melhor começar com a forma mais simples e construir a partir daí.

MichaelHouse
fonte
Eu simplesmente não consigo descobrir o que fazer em casos como "problemas com Newton" nesta imagem. Por exemplo, como definir a ordem dessas linhas no código sem repeti-las.
user1306322
Você encontrará frequentemente que o diálogo pode ser repetido. Geralmente é marcado apenas de alguma forma, para que o usuário saiba que já escolheu esse caminho de caixa de diálogo. Você pode colocar uma bandeira nas bordas, indicando se elas já foram selecionadas antes. Portanto, cabe a você permitir que os usuários o selecionem novamente (para se atualizarem) ou não mostrá-lo.
MichaelHouse
11
Normalmente, isso não seria feito com a ordem das linhas de código, mas através das referências na estrutura de dados.
Kylotan
7

Eu construí um sistema simples de dialogtree: http://iki.fi/sol/d3/ atualmente o "mecanismo" é simples c, mas os dados produzidos pelo editor são bastante simples de usar em qualquer idioma. A ferramenta gera XML, JSON e um formato binário personalizado.

O conceito principal é bem simples:

Você está em um labirinto de pequenas passagens sinuosas, todas iguais

Cada nó (que chamo de "cartão", como no análogo acima) da caixa de diálogo consiste em texto de pergunta e zero ou mais respostas. Cada uma das respostas leva a outro cartão.

Há também um sistema de tags em que certas respostas são mostradas ao usuário apenas se uma tag estiver definida (ou uma tag não estiver definida). A inserção de um cartão define (ou desativa) as tags especificadas.

Isso é praticamente tudo o que precisamos fazer sobre qualquer tipo de diálogo em um jogo. O "texto da pergunta" pode ser um texto sem formatação ou um script para gerar animação ou outros enfeites.

Jari Komppa
fonte
4

Você pode usar o TreeSharp e as árvores de comportamento para modelar um sistema de diálogo. TreeSharp é uma biblioteca que fornece uma implementação simples da árvore de comportamento. Os bots IA para wow são feitos com isso, então é maduro ... :)

Minha implementação possui nós que permitem escolher entre respostas, e cada resposta pode ser associada a um diálogo ou uma ação, ou uma sequência de ações, ou um nó que permite ir para outro diálogo ... ou o que você deseja ...

Eu usei o brainiac editor para torná-lo visualmente ... mas no final ele produz código c # baseado em treesharp ...

http://www.youtube.com/watch?v=6uGg6bUYyUU

Blau
fonte
2

Você deseja um gráfico direcionado (possivelmente cíclico).

Você modelaria os nós como objetos, e todas as setas de saída no nó de um gráfico também serão modeladas como objetos separados. O nó possui uma lista de setas de saída e cada objeto "seta" possui um texto para exibir e uma referência ao destino. Não tenho certeza, mas acho que os objetos C # sempre são referenciados; portanto, basta criar os objetos primeiro e, em seguida, ao criar os objetos de seta, conecte o mesmo objeto ao campo de destino de duas setas. (Em C ++, você usaria um tipo de referência ou ponteiro, Nó e ou Nó *)

Para carregar coisas como essa do disco, geralmente se atribui a cada nó um número de identificação exclusivo e, em seguida, carrega todos os nós em uma matriz em que o índice é esse número único. Em seguida, as setas são serializadas escrevendo o número, não o objeto real.

Ao carregar uma seta, você usa a matriz e o ID para obter uma referência ao nó para o qual aponta. Se você escrevesse o objeto duas vezes, obteria dois objetos separados que parecem idênticos, o que provavelmente não é o que você queria.

O processamento de uma árvore de diálogo se torna muito simples. Você apenas coloca o nó raiz em uma currentNodevariável, exibe a coisa toda de alguma forma e, quando uma escolha é feita, defina rootNodeo destino da seta. No pseudocódigo:

Node&    currentNode = dialogTree.node[0];
while( currentNode != END_CONVERSATION_PSEUDO_NODE )
{
    stage.displayNode( currentNode );
    currentNode = stage.waitForUserToChoose();
}
uliwitness
fonte
1

Recentemente, tive que desenvolver algo assim usando o Node e optei por uma estrutura de arquivo de texto muito básica para representar um gráfico direcionado de nós de conversação.

Você pode ver o código resultante e o formato do texto em:

https://github.com/scottbw/dialoguejs

Ainda não suporta condições ou gatilhos de eventos, mas provavelmente é simples o suficiente para muitos desenvolvedores de jogos.

(O próprio código na GPL, btw)

Scott Wilson
fonte
A pergunta pede C #.
Seth Battin
D'oh - desculpe por isso.
Scott Wilson