Jak działają drzewa dialogowe?

20

To znaczy, co jest związane z czym i jak poruszać się między liniami mowy po zakończeniu pod-rozmowy?

Jeśli masz jakieś przykłady podstawowego drzewa dialogowego w C #, opublikuj je.

użytkownik1306322
źródło
Myślę, że byłoby wspaniale mieć dialog-treetag.
user1306322
Pytanie o próbki kodu zwykle nie jest mile widziane.
MichaelHouse
Jeśli istnieje kilka przykładów kodu drzewa dialogowego 101, które warto udostępnić, nie zaszkodzi.
user1306322
Problem polega na tym, że w tej witrynie chodzi o uzyskiwanie poprawnych odpowiedzi na pytania. Nie służy do zbierania próbek kodu.
MichaelHouse
Dlatego zdanie zaczyna się od „jeśli”. Ale proszę o wyjaśnienie, w jaki sposób linie dialogowe łączą się ze sobą w sposób, który można skutecznie przetłumaczyć na kod. W końcu napiszę to w C #.
user1306322

Odpowiedzi:

24

Nazwa „drzewo dialogu” jest nieco myląca - zwykle są to proste wykresy skierowane , a nie tylko drzewa . Podstawowa struktura danych takich wykresów zwykle składa się z pewnego rodzaju „danych” dla węzłów, które reprezentują punkty, w których jesteśmy w rozmowie, i łączy ich z innymi węzłami, które reprezentują to, co mówią i robią uczestnicy i opcjonalnie mają warunki, aby ograniczyć ich widoczność lub skrypty do wykonywania różnych dodatkowych działań. Zwykle jeden z węzłów jest domyślnym węzłem początkowym (typowe etykiety to „ROOT”, „START” i „POWITANIE”), a węzły, które nie prowadzą od nich prawidłowe łącza, kończą rozmowę.

W większości przypadków wykres jest reprezentowany w pamięci jako lista Nodestruktur danych, z których każda ma co najmniej identyfikator i listę Linkstruktur danych 0..n . Lista może być lokalna dla NPC lub globalna; Drugi przypadek jest preferowany, jeśli masz dużo ogólnych NPC, z którymi można porozmawiać w celu uzyskania informacji, ale nie oferują oni żadnych konkretnych rozmów na własną rękę. Sam system znajduje początkowy węzeł konwersacji dla NPC, zapamiętuje swój identyfikator jako bieżący identyfikator konwersacji, przedstawia aktualnie ważne linki do wyboru przez gracza (lub „[zakończ rozmowę]”, jeśli nie ma prawidłowych linków) i czeka na Wejście. Gdy gracz wybierze łącze, zostaną wyświetlone powiązane linie dialogowe i uruchomione zostaną powiązane skrypty.

Zamiast mieć skomplikowane reguły i warunki dotyczące linków, możesz zamiast tego poradzić sobie z prostą „prawidłową” zmienną logiczną, którą można następnie zmienić ze skryptów innych linków konwersacji (w tym domyślnej z węzła początkowego) lub z zewnątrz mechanizmy Ogólnie rzecz biorąc, takie podejście jest prostsze, ale nadaje się tylko do gier z bardzo małą liczbą takich rozmów, ponieważ przesuwa logikę „Kiedy ta odpowiedź jest możliwa?” z dala od samych danych odpowiedzi.


Zauważ, że struktura, którą tu opisuję, różni się nieco od Byte56, ponieważ węzły nie muszą mieć żadnych linii dialogowych; linki mogą mieć je wszystkie. W najbardziej podstawowym wariancie przekłada się to na następującą strukturę.

wprowadź opis zdjęcia tutaj

Martin Sojka
źródło
+1 Aby wspomnieć o zasadach i warunkach dotyczących linków, prosty ukierunkowany wykres często nie wystarcza, a kiedy zaczyna się ich potrzebować, sprawy mogą się skomplikować.
Laurent Couvidou
+1 Bardziej podoba mi się ta struktura. Chociaż nie poleciłbym tego jako pierwszego przejścia. Zacznę od czegoś prostszego. Z pewnością jest to lepszy cel do strzelania.
MichaelHouse
+1 Za bardzo szczegółową odpowiedź. Może mi się to później przydać.
Marton,
Ten obraz był dla mnie bardzo pomocny, ale muszę się zastanawiać, dlaczego DialogueLine jest oddzielony od linku? Czy każdy link nie miałby własnego tekstu odpowiedzi? A dokąd poszedłby tekst NPC? Czy nie ma sensu mieć go w węźle?
Kyle Baran
@ Danjen W tej strukturze Link może mieć wiele DialogueLine, prawdopodobnie różnych znaków, aż pojawi się następny wybór dialogu. Tu także idzie tekst NPC. Kiedy linie się powtarzają, różne łącza mogą współdzielić linie DialogueLine, ewentualnie zmieniając ich kolejność na liście (Vector), zastępując ich części różnymi liniami, dodając wykrzykniki i tak dalej.
Martin Sojka
16

Drzewa dialogowe są tworzone z ukierunkowaną strukturą grafu .

wprowadź opis zdjęcia tutaj

Wykres jest przesuwany w oparciu o decyzje dialogowe podejmowane przez gracza. Opcje dialogowe udostępnione użytkownikowi pochodzą z krawędzi, które definiują ścieżki do innych węzłów okna dialogowego.

Grafy kierunkowe są podstawową strukturą danych. Można je łatwo wdrożyć i prawdopodobnie będziesz chciał je wdrożyć samodzielnie. Ponieważ będziesz chciał dostosować wykres do swoich potrzeb w oknie dialogowym.

Niektóre z węzłów mogą wymagać spełnienia specjalnych warunków w celu wyświetlenia. Na przykład gracz wymagałby umiejętności mówienia powyżej X. Lub gracz musi ukończyć misję Z, zanim będzie mógł przejść jedną gałąź dialogu. Lub muszą zapytać o coś 4 razy, zanim NPC je przedyskutuje. Te funkcje będą dostosowane do twojej gry. Warto jednak wspomnieć o implementacji przejścia przez węzeł i krawędź. Oczywiście zawsze najlepiej jest zacząć od najprostszej formy i stamtąd rozbudowywać.

MichaelHouse
źródło
Po prostu nie mogę wymyślić, co robić w przypadkach takich jak „kłopoty Newtona” na tym zdjęciu. Jak ustawić kolejność tych wierszy w kodzie bez ich powtarzania.
user1306322
Często okaże się, że okno dialogowe można powtórzyć. Zazwyczaj jest to w jakiś sposób oznaczone, aby użytkownik wiedział, że już wybrał tę ścieżkę okna dialogowego. Możesz umieścić flagę na krawędziach, która wskazuje, czy zostały wcześniej wybrane. Zatem do Ciebie należy zezwolenie użytkownikom na ponowne wybranie go (odświeżenie się) lub nie pokazanie go.
MichaelHouse
1
Zwykle nie można tego zrobić przy uporządkowaniu wierszy kodu, ale poprzez odwołania w strukturze danych.
Kylotan
7

Zbudowałem prosty system dialogowy: http://iki.fi/sol/d3/ sam silnik jest obecnie zwykły c, ale dane wytworzone przez edytor są dość proste w użyciu w dowolnym języku. Narzędzie generuje XML, JSON i niestandardowy format binarny.

Główna koncepcja jest dość prosta:

Jesteś w labiryncie krętych małych pasaży, wszystkie podobne

Każdy węzeł (który nazywam „kartą”, jak w powyższym analogu) okna dialogowego składa się z tekstu pytania i zera lub więcej odpowiedzi. Każda z odpowiedzi prowadzi do innej karty.

Istnieje również system tagów, w którym pewne odpowiedzi są wyświetlane użytkownikowi tylko wtedy, gdy tag jest ustawiony (lub tag nie jest ustawiony). Wprowadzanie zestawów kart (lub odblokowań) określonych znaczników.

To prawie wszystko, co trzeba zrobić w przypadku każdego rodzaju dialogu w grze. „Tekst pytania” może być zwykłym tekstem lub skryptem do animacji lub czymkolwiek innym.

Jari Komppa
źródło
4

Za pomocą TreeSharp i drzew zachowań można modelować system dialogowy. TreeSharp to biblioteka, która zapewnia prostą implementację drzewa zachowań. Roboty IA dla wow są z tym zrobione, więc są dojrzałe ... :)

Moja implementacja ma węzły, które pozwalają wybierać między odpowiedziami, a do każdej odpowiedzi można dołączyć dialog lub akcję, sekwencję akcji lub węzeł, który pozwala przejść do innego okna dialogowego ... lub czego chcesz ...

Użyłem edytora mózgu, aby zrobić to wizualnie ... ale na koniec produkuje kod c # na podstawie ostrza drzewa ...

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

Blau
źródło
2

Chcesz skierowany (prawdopodobnie cykliczny) wykres.

Modelujesz węzły jako obiekty, a wszystkie strzałki wychodzące w węźle wykresu są również modelowane jako osobne obiekty. Węzeł ma listę wychodzących strzał, a każdy obiekt „strzałkowy” ma tekst do wyświetlenia i odniesienie do miejsca docelowego. Nie jestem pewien, ale myślę, że w C # obiekty są zawsze przywoływane, więc najpierw tworzysz obiekty, a następnie, gdy tworzysz obiekty strzałek, podłącz ten sam obiekt do pola docelowego dwóch strzałek. (W C ++ użyłbyś referencji lub typu wskaźnika, Węzeł i lub Węzeł *)

Aby załadować takie rzeczy z dysku, zwykle nadaje się każdemu węzłowi unikalny numer identyfikacyjny, a następnie ładuje wszystkie węzły do ​​tablicy, w której indeks jest tym unikalnym numerem. Następnie strzałki są serializowane przez zapisanie numeru, a nie rzeczywistego obiektu.

Podczas ładowania strzałki używasz tablicy i identyfikatora, aby uzyskać odwołanie do węzła, na który wskazuje. Jeśli wypiszesz obiekt dwukrotnie, otrzymasz dwa osobne obiekty, które wyglądają identycznie, co prawdopodobnie nie jest tym, czego chciałeś.

Przetwarzanie drzewa dialogowego staje się bardzo proste. Po prostu umieścisz węzeł główny w currentNodezmiennej, jakoś wyświetlisz całą rzecz, a następnie, gdy zostanie dokonany wybór, ustaw rootNodemiejsce docelowe strzałki. W pseudokodzie:

Node&    currentNode = dialogTree.node[0];
while( currentNode != END_CONVERSATION_PSEUDO_NODE )
{
    stage.displayNode( currentNode );
    currentNode = stage.waitForUserToChoose();
}
wszechstronność
źródło
1

Niedawno musiałem opracować coś takiego za pomocą Węzła i zdecydowałem się na bardzo podstawową strukturę pliku tekstowego, która reprezentowałaby ukierunkowany wykres węzłów konwersacji.

Wynikowy kod i format tekstowy możesz zobaczyć na:

https://github.com/scottbw/dialoguejs

Nie obsługuje warunków ani wyzwalaczy zdarzeń (jeszcze), ale prawdopodobnie jest wystarczająco prosty, aby zacząć od wielu twórców gier.

(Sam kod w GPL, btw)

Scott Wilson
źródło
Pytanie dotyczy C #.
Seth Battin
D'oh - przepraszam za to.
Scott Wilson