Как работают диалоговые деревья?

20

То есть, что связано с чем и как перемещаться между строками речи, когда заканчивается разговор?

Если у вас есть примеры базового дерева диалогов в C #, пожалуйста, опубликуйте их.

user1306322
источник
Я думаю, было бы здорово иметь dialog-treeтег.
user1306322
Запросы на примеры кода обычно не воспринимаются благоприятно.
MichaelHouse
Если есть некоторые примеры кода в диалоговом дереве 101, которые стоит поделиться, это не повредит.
user1306322
Проблема в том, что этот сайт посвящен получению правильных ответов на вопросы. Это не для сбора примеров кода.
MichaelHouse
Вот почему предложение начинается с «если». Но то, что я прошу, - это объяснение того, как строки диалога соединяются друг с другом таким способом, который может быть эффективно переведен в код. В конце концов я собираюсь написать это на C #.
user1306322

Ответы:

24

Название «диалоговое дерево» немного вводит в заблуждение - обычно это простые ориентированные графы , а не просто деревья . Базовая структура данных таких графиков обычно состоит из неких «данных» для узлов, которые представляют точки, в которых мы находимся в разговоре, и ссылок от них на другие узлы, которые представляют то, что говорят и делают участники и при желании иметь условия для них, чтобы ограничить их видимость или сценарии для выполнения различных дополнительных действий. Обычно один из узлов является начальным узлом по умолчанию (типичными метками для этого являются «ROOT», «START» и «GREETING»), а узлы, у которых нет действительных ссылок, ведущих из них, завершают диалог.

В большинстве случаев график представляется в памяти в виде списка Nodeструктур данных, каждая из которых имеет по меньшей мере идентификатор и список 0..n Linkструктур данных. Список может быть локальным для NPC или глобальным; второй случай предпочтителен, если у вас есть много общих NPC, с которыми можно поговорить для информации, но не предлагать никаких конкретных разговоров самостоятельно. Система сама находит начальный узел разговора для NPC, запоминает его идентификатор в качестве идентификатора текущего разговора, представляет действующие в настоящий момент ссылки для выбора игрока (или «[конец разговора]», если нет действительных ссылок) и ожидает вход. Когда игрок выбирает ссылку, отображаются соответствующие диалоговые строки и запускаются все связанные сценарии.

Вместо сложных правил и условий для ссылок вы можете вместо этого использовать простую «допустимую» логическую переменную, которую затем можно изменить либо из сценариев других диалоговых ссылок (включая сценарий по умолчанию из начального узла), либо из внешних источников. механизмы. В общем, этот подход проще, но подходит только для игр с очень небольшим количеством таких разговоров, поскольку он перемещает логику «Когда возможен этот ответ?» вдали от самих данных ответа.


Обратите внимание, что структура, которую я здесь описываю, немного отличается от структуры Byte56 тем, что узлы не должны иметь никаких строк диалога; ссылки могут иметь их все. В самом основном варианте это переводится в следующую структуру.

введите описание изображения здесь

Мартин Сойка
источник
+1 Для упоминания правил и условий в ссылках простого ориентированного графа часто недостаточно, и все может стать сложным, когда вы начнете нуждаться в них.
Лоран Кувиду
+1 Мне больше нравится эта структура. Хотя я бы не рекомендовал это как первый проход. Я бы начал с чего-то более простого. Это, безусловно, лучшая цель для стрельбы.
MichaelHouse
+1 За очень подробный ответ. Это может пригодиться мне позже.
Мартон
Это изображение было очень полезным для меня, но мне интересно, почему DialogueLine отделен от Link? Разве у каждой ссылки не будет своего текста ответа? И куда пойдет текст NPC? Разве не имеет смысла иметь его в узле?
Кайл Баран
@Danjen В этой структуре Ссылка может иметь несколько DialogueLines, возможно, от разных символов, пока не появится следующий выбор диалога. Это также, где текст NPC идет. Когда строки повторяются, разные ссылки могут совместно использовать DialogueLines, возможно, переупорядочивая их в своем списке (Vector), заменяя их части различными линиями, добавляя междометия и так далее.
Мартин Сойка
16

Деревья диалогов создаются с помощью структуры ориентированного графа .

введите описание изображения здесь

График перемещается на основе диалоговых решений, которые принимает игрок. Параметры диалога, предоставляемые пользователю, происходят от краев, которые определяют пути к другим узлам диалога.

Ориентированные графы являются базовой структурой данных. Они могут быть легко реализованы, и вы, вероятно, захотите реализовать это самостоятельно. Так как вы захотите адаптировать график к вашим потребностям в диалоге.

Некоторые узлы могут иметь особые условия для отображения. Например, игроку потребуется навык речи выше X. Или игрок должен завершить миссию Z, прежде чем он сможет пройти вниз по одной ветви диалога. Или они должны спросить что-то 4 раза, прежде чем NPC обсудит это с ними. Эти функции будут индивидуальны для вашей игры. Но стоит упомянуть, когда вы реализуете обход узлов и ребер. Конечно, всегда лучше начинать с самой простой формы и строить ее оттуда.

MichaelHouse
источник
Я просто не могу понять, что делать в таких случаях, как «проблема Ньютона» на этой картинке. Например, как установить порядок этих строк в коде, не повторяя их.
user1306322
Вы часто обнаружите, что диалог может быть повторен. Обычно он просто помечается, так что пользователь знает, что он уже выбрал этот путь диалога. Вы можете поставить флажки по краям, которые указывают, были ли они выбраны ранее. Поэтому вам нужно либо позволить пользователям выбрать его снова (чтобы обновить себя), либо не показывать его.
MichaelHouse
1
Обычно это делается не с упорядочением строк кода, а с помощью ссылок в структуре данных.
Kylotan
7

Я построил простую систему диалогового дерева: http://iki.fi/sol/d3/ сам «движок» в настоящее время просто c, но данные, создаваемые редактором, довольно просты в использовании на любом языке. Инструмент выводит XML, JSON и пользовательский двоичный формат.

Основная концепция довольно проста:

Вы находитесь в лабиринте извилистых маленьких проходов, всех одинаково

Каждый узел (который я называю «карточкой», как и в приведенном выше аналоге) диалога состоит из текста вопроса и ноля или более ответов. Каждый из ответов ведет к другой карточке.

Существует также система тегов, где определенные ответы показываются пользователю, только если тег установлен (или тег не установлен). Ввод карты устанавливает (или отменяет) указанные теги.

Это почти все, что нужно для любого диалогового окна в игре. «Текст вопроса» может быть простым текстом или сценарием для управления анимацией или еще чем-то.

Яри ​​Комппа
источник
4

Вы можете использовать TreeSharp и деревья поведения для моделирования диалоговой системы. TreeSharp - это библиотека, которая обеспечивает простую реализацию дерева поведения. ИА боты для вау с этим покончено, так что уже пора ... :)

В моей реализации есть узлы, которые позволяют выбирать между ответами, и каждый ответ может быть присоединен к другому диалогу или действию, или последовательности действий, или узлу, который позволяет перейти к другому диалогу ... или что вы хотите ...

Я использовал мозговой редактор, чтобы сделать это визуально ... но в конце он производит код на C # на основе Treeharp ...

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

Blau
источник
2

Вы хотите ориентированный (возможно, циклический) граф.

Вы бы смоделировали узлы как объекты, и все исходящие стрелки в узле графа также моделируются как отдельные объекты. Узел имеет список исходящих стрелок, и каждый объект «стрелка» имеет текст для отображения и ссылку на пункт назначения. Не уверен, но я думаю, что в C # на объекты всегда ссылаются, поэтому сначала вы просто создаете объекты, а затем, когда вы создаете объекты стрелок, вставляете один и тот же объект в поле назначения двух стрелок. (В C ++ вы бы использовали ссылку или тип указателя, Node & или Node *)

Для загрузки таких вещей с диска обычно присваивают каждому узлу уникальный идентификационный номер, а затем загружают все узлы в массив, индекс которого является этим уникальным номером. Затем стрелки сериализуются путем записи числа, а не самого объекта.

Когда вы загружаете стрелку, вы используете массив и идентификатор, чтобы получить ссылку на узел, на который она указывает. Если вы выписали объект дважды, вы получите два отдельных объекта, которые просто выглядят одинаково, что, вероятно, не то, что вы хотели.

Обработка диалогового дерева становится очень простой. Вы просто помещаете корневой узел в currentNodeпеременную, как-то отображаете все это, а затем, когда выбор сделан, устанавливаете rootNodeпункт назначения стрелки. В псевдокоде:

Node&    currentNode = dialogTree.node[0];
while( currentNode != END_CONVERSATION_PSEUDO_NODE )
{
    stage.displayNode( currentNode );
    currentNode = stage.waitForUserToChoose();
}
uliwitness
источник
1

Недавно мне пришлось разработать что-то подобное с помощью Node, и я выбрал очень простую структуру текстового файла для представления ориентированного графа узлов разговора.

Вы можете увидеть полученный код и текстовый формат по адресу:

https://github.com/scottbw/dialoguejs

Он не поддерживает условия или триггеры событий (пока), но, вероятно, достаточно прост для начала для многих разработчиков игр.

(Сам код в GPL, кстати)

Скотт Уилсон
источник
Вопрос просит C #.
Сет Баттин
Ох, прости за это.
Скотт Уилсон