ต้นไม้ไดอะล็อกทำงานอย่างไร


20

นั่นคือสิ่งที่เชื่อมต่อกับสิ่งที่และวิธีการย้ายระหว่างบรรทัดคำพูดเมื่อการสนทนาย่อยสิ้นสุดลง?

หากคุณมีตัวอย่างของแผนภูมิโต้ตอบพื้นฐานใน C # โปรดโพสต์ไว้


ฉันคิดว่ามันคงจะดีถ้ามีdialog-treeแท็ก
user1306322

การขอตัวอย่างรหัสมักไม่ได้รับความสนใจ
MichaelHouse

หากมีไดอะล็อกตัวอย่างโค้ด 101 รายการที่คุ้มค่าต่อการแบ่งปันมันจะไม่เป็นอันตราย
user1306322

ปัญหาคือเว็บไซต์นี้เกี่ยวกับการรับคำตอบที่ถูกต้องสำหรับคำถาม ไม่ใช่เพื่อรวบรวมตัวอย่างโค้ด
MichaelHouse

นั่นเป็นเหตุผลที่ประโยคเริ่มต้นด้วย "ถ้า" แต่สิ่งที่ฉันขอคือคำอธิบายว่าสายโต้ตอบเชื่อมต่อซึ่งกันและกันในวิธีที่สามารถแปลรหัสได้อย่างมีประสิทธิภาพ หลังจากทั้งหมดฉันจะเขียนมันใน C #
user1306322

คำตอบ:


24

ชื่อ "ต้นบทสนทนา" เป็นบิตทำให้เข้าใจผิด - พวกเขามักจะกราฟระบุทิศทางที่เรียบง่ายไม่เพียง แต่ต้นไม้ โครงสร้างข้อมูลพื้นฐานของกราฟดังกล่าวมักจะประกอบด้วย "ข้อมูล" บางอย่างสำหรับโหนดซึ่งเป็นตัวแทนของจุดที่เราอยู่ในการสนทนาและการเชื่อมโยงจากพวกเขาไปยังโหนดอื่น ๆ ซึ่งเป็นตัวแทนของสิ่งที่ถูกพูดและทำโดยผู้เข้าร่วม และอาจมีเงื่อนไขให้ จำกัด การมองเห็นหรือสคริปต์เพื่อดำเนินการเพิ่มเติมต่างๆ โดยปกติหนึ่งในโหนดคือโหนดเริ่มต้นเริ่มต้น (ป้ายกำกับทั่วไปสำหรับที่คือ "ROOT", "START" และ "GREETING") และโหนดที่ไม่มีลิงก์ที่ถูกต้องซึ่งนำไปสู่การสิ้นสุดการสนทนา

ในกรณีส่วนใหญ่กราฟจะถูกแสดงในหน่วยความจำว่าเป็นรายการของNodeโครงสร้างข้อมูลแต่ละอันมี ID อย่างน้อยและรายการของLinkโครงสร้างข้อมูล0..n รายการสามารถเป็นแบบโลคัลกับ NPC หรือแบบโกลบอล กรณีที่สองเป็นที่ต้องการหากคุณมี NPC ทั่วไปจำนวนมากซึ่งสามารถพูดคุยเพื่อขอข้อมูลได้ แต่ไม่มีการสนทนาที่เฉพาะเจาะจงด้วยตนเอง ระบบจะค้นหาโหนดการสนทนาเริ่มต้นสำหรับ NPC โดยจดจำ ID เป็น ID การสนทนาปัจจุบันแสดงลิงก์ที่ถูกต้องในปัจจุบันสำหรับผู้เล่นที่จะเลือกจาก (หรือ "[การสนทนาสิ้นสุด]" หากไม่มีลิงก์ที่ถูกต้อง) และรอ อินพุต เมื่อผู้เล่นเลือกลิงค์เส้นสนทนาที่เกี่ยวข้องจะปรากฏขึ้นและสคริปต์ที่เกี่ยวข้องจะทำงาน

แทนที่จะมีกฎและเงื่อนไขที่ซับซ้อนในการเชื่อมโยงคุณสามารถรับโดยใช้ตัวแปรบูลีน "ที่ถูกต้อง" อย่างง่ายซึ่งสามารถเปลี่ยนได้จากสคริปต์ของลิงก์การสนทนาอื่น ๆ (รวมถึงค่าเริ่มต้นจากโหนดเริ่มต้น) หรือภายนอก กลไก โดยทั่วไปวิธีการนี้จะง่ายกว่า แต่เหมาะสำหรับเกมที่มีการสนทนาน้อยมากเนื่องจากจะย้ายตรรกะของ "การตอบสนองนี้จะเกิดขึ้นเมื่อใด" ห่างจากข้อมูลตอบกลับเอง


โปรดทราบว่าโครงสร้างที่ฉันอธิบายที่นี่แตกต่างจาก Byte56 เล็กน้อยในการที่โหนดไม่จำเป็นต้องมีสายการสนทนาใด ๆ ลิงก์สามารถมีได้ทั้งหมด ในตัวแปรพื้นฐานที่สุดสิ่งนี้แปลเป็นโครงสร้างต่อไปนี้

ป้อนคำอธิบายรูปภาพที่นี่


+1 สำหรับการกล่าวถึงกฎและเงื่อนไขในลิงก์กราฟกำกับง่ายมักไม่เพียงพอและสิ่งต่าง ๆ อาจซับซ้อนเมื่อคุณต้องการใช้
Laurent Couvidou

+1 ฉันชอบโครงสร้างนั้นดีกว่า แม้ว่าฉันจะไม่แนะนำเป็นครั้งแรก ฉันจะเริ่มต้นด้วยสิ่งที่ง่ายกว่า แน่นอนว่าเป็นเป้าหมายที่ดีกว่าสำหรับการยิง
MichaelHouse

+1 สำหรับคำตอบที่ละเอียดมาก สิ่งนี้อาจมีประโยชน์สำหรับฉันในภายหลัง
Marton

ภาพนี้มีประโยชน์กับฉันมาก แต่ฉันต้องสงสัยว่าทำไม DialogueLine แยกจากลิงก์ แต่ละลิงก์จะไม่มีข้อความตอบกลับเป็นของตัวเองหรือ และข้อความของ NPC จะไปอยู่ที่ไหน มันจะไม่สมเหตุสมผลที่จะมีอยู่ในโหนดหรือไม่?
Kyle Baran

@Danjen ในโครงสร้างนี้ลิงก์สามารถมี DialogueLines ได้หลายตัวซึ่งอาจมาจากตัวอักษรที่แตกต่างกันจนกระทั่งตัวเลือกการสนทนาถัดไปปรากฏขึ้น นี่คือตำแหน่งที่ข้อความ NPC ไปด้วย เมื่อบรรทัดเกิดซ้ำลิงก์ต่าง ๆ สามารถแบ่งปัน DialogueLines ซึ่งอาจเรียงลำดับใหม่ในรายการ (Vector) แทนที่ส่วนต่าง ๆ ของพวกเขาด้วยเส้นต่าง ๆ เพิ่มการแทรกแทรกและอื่น ๆ
Martin Sojka

16

ต้นไม้โต้ตอบที่ถูกสร้างขึ้นด้วยโครงสร้างกราฟ

ป้อนคำอธิบายรูปภาพที่นี่

กราฟจะถูกสำรวจตามการตัดสินใจของผู้เล่น ตัวเลือกการโต้ตอบที่มีให้กับผู้ใช้นั้นมาจากขอบที่กำหนดเส้นทางไปยังโหนดการโต้ตอบอื่น ๆ

กราฟกำกับเป็นโครงสร้างข้อมูลพื้นฐาน สามารถนำไปใช้ได้อย่างง่ายดายและคุณอาจต้องการนำไปใช้ด้วยตนเอง เนื่องจากคุณต้องการปรับกราฟตามความต้องการของกล่องโต้ตอบ

บางโหนดอาจต้องมีเงื่อนไขพิเศษเพื่อให้ปรากฏขึ้น ตัวอย่างเช่นผู้เล่นจะต้องใช้ทักษะในการพูดข้างต้น X หรือผู้เล่นจะต้องเสร็จสิ้นภารกิจ Z ก่อนที่พวกเขาจะสามารถดำเนินการโต้ตอบหนึ่งสาขา หรือพวกเขาต้องถามบางสิ่ง 4 ครั้งก่อนที่ NPC จะพูดคุยกับพวกเขา คุณสมบัติเหล่านี้จะถูกกำหนดให้กับเกมของคุณ แต่น่าจะพูดถึงเมื่อคุณใช้โหนดและการข้ามผ่านขอบ แน่นอนว่ามันเป็นการดีที่สุดที่จะเริ่มต้นด้วยรูปแบบที่ง่ายที่สุดและสร้างขึ้นจากที่นั่น


ฉันคิดไม่ออกว่าจะทำอย่างไรในกรณีเช่น "Newton-problems" ในภาพนี้ เช่นเดียวกับวิธีตั้งค่าลำดับของบรรทัดเหล่านั้นในโค้ดโดยไม่ต้องทำซ้ำ
user1306322

คุณมักจะพบว่าสามารถโต้ตอบซ้ำได้ โดยปกติจะมีการทำเครื่องหมายด้วยวิธีใดวิธีหนึ่งเพื่อให้ผู้ใช้รู้ว่าพวกเขาเลือกเส้นทางกล่องโต้ตอบนั้นแล้ว คุณสามารถวางธงลงบนขอบของคุณเพื่อระบุว่าพวกเขาได้รับการคัดเลือกมาก่อนหรือไม่ ดังนั้นขึ้นอยู่กับคุณว่าจะอนุญาตให้ผู้ใช้เลือกอีกครั้ง (เพื่อรีเฟรชตัวเอง) หรือไม่แสดง
MichaelHouse

1
ปกติแล้วจะไม่สามารถทำได้ด้วยการเรียงลำดับบรรทัดของรหัส แต่ผ่านการอ้างอิงในโครงสร้างข้อมูล
Kylotan

7

ฉันได้สร้างระบบ dialogtree ง่าย ๆ : http://iki.fi/sol/d3/ ตัว "engine" นั้นเป็นธรรมดา c แต่ข้อมูลที่ผลิตโดยโปรแกรมแก้ไขนั้นค่อนข้างใช้งานง่ายในภาษาใด ๆ เครื่องมือเอาต์พุต XML, JSON และรูปแบบไบนารีที่กำหนดเอง

แนวคิดหลักเรียบง่าย:

คุณอยู่ในเขาวงกตของทางเดินเล็ก ๆ ที่คดเคี้ยวเหมือนกันทั้งหมด

แต่ละโหนด (ที่ฉันเรียกว่า "การ์ด" เช่นเดียวกับอะนาล็อกข้างต้น) ของกล่องโต้ตอบประกอบด้วยข้อความคำถามและคำตอบที่เป็นศูนย์หรือมากกว่า คำตอบแต่ละข้อนำไปสู่การ์ดใบใหม่

นอกจากนี้ยังมีระบบแท็กที่แสดงคำตอบบางอย่างแก่ผู้ใช้เฉพาะเมื่อมีการตั้งค่าแท็ก (หรือไม่ได้ตั้งค่าแท็ก) การป้อนแท็กที่ระบุชุด (หรือ unsets) บัตร

นี่คือทุกสิ่งที่เราต้องการทำในบทสนทนาใด ๆ ในเกม "ข้อความคำถาม" อาจเป็นข้อความธรรมดาหรืออาจเป็นสคริปต์ในการขับเคลื่อนภาพเคลื่อนไหวหรืออะไรก็ตาม


4

คุณสามารถใช้ TreeSharp และต้นไม้พฤติกรรมเพื่อสร้างแบบจำลองระบบการสนทนา TreeSharp เป็นห้องสมุดที่ให้การใช้งานต้นไม้อย่างง่าย IA บอทสำหรับว้าวเสร็จแล้วด้วยดังนั้นมันจึงเป็นผู้ใหญ่ ... :)

การใช้งานของฉันมีโหนดที่ให้เลือกระหว่างคำตอบและแต่ละคำตอบสามารถเข้าร่วมกับการสนทนา othe หรือการกระทำหรือลำดับของการกระทำหรือโหนดที่ช่วยให้ไปที่กล่องโต้ตอบอื่น ... หรือสิ่งที่คุณต้องการ ...

ฉันใช้เครื่องมือแก้ไขอัจฉริยะเพื่อทำให้มองเห็น ... แต่ท้ายที่สุดมันสร้างรหัส c # ตาม treesharp ...

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


2

คุณต้องการกราฟกำกับ (อาจเป็นวงกลม)

คุณต้องการสร้างแบบจำลองโหนดเป็นวัตถุและลูกศรที่ส่งออกทั้งหมดในโหนดของกราฟนั้นถูกสร้างแบบจำลองเป็นวัตถุแยกต่างหากเช่นกัน โหนดมีรายการลูกศรที่ส่งออกและวัตถุ "ลูกศร" แต่ละอันมีข้อความที่จะแสดงและการอ้างอิงไปยังปลายทาง ไม่แน่ใจ แต่ฉันคิดว่าในวัตถุ C # นั้นมีการอ้างอิงอยู่เสมอดังนั้นคุณเพียงแค่สร้างวัตถุก่อนจากนั้นเมื่อคุณสร้างวัตถุลูกศรให้เสียบวัตถุเดียวกันลงในช่องปลายทางของลูกศรสองตัว (ใน C ++ คุณต้องใช้การอ้างอิงหรือประเภทตัวชี้ Node & หรือ Node *)

สำหรับการโหลดสิ่งต่าง ๆ เช่นนี้จากดิสก์มักจะให้หมายเลข ID ที่ไม่ซ้ำกันในแต่ละโหนดจากนั้นโหลดโหนดทั้งหมดลงในอาร์เรย์ที่ดัชนีเป็นหมายเลขเฉพาะ จากนั้นลูกศรจะถูกจัดลำดับโดยการเขียนตัวเลขไม่ใช่วัตถุจริง

เมื่อคุณโหลดลูกศรคุณจะใช้อาร์เรย์และ ID เพื่อรับการอ้างอิงไปยังโหนดที่ชี้ไป หากคุณเขียนวัตถุออกมาสองครั้งคุณจะได้รับวัตถุสองชิ้นแยกกันที่ดูเหมือนกันซึ่งอาจไม่ใช่สิ่งที่คุณต้องการ

การประมวลผลแผนผังต้นไม้กลายเป็นเรื่องง่ายมาก คุณเพียงแค่ใส่รูทโหนดในcurrentNodeตัวแปรแสดงทุกสิ่งอย่างใดอย่างหนึ่งจากนั้นเมื่อมีการเลือกให้ตั้งค่าrootNodeเป็นปลายทางของลูกศร ใน pseudocode:

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

1

เมื่อเร็ว ๆ นี้ฉันต้องพัฒนาบางอย่างเช่นนี้โดยใช้ Node และเลือกโครงสร้างไฟล์ข้อความพื้นฐานเพื่อแสดงกราฟกำกับของโหนดการสนทนา

คุณสามารถดูโค้ดผลลัพธ์และรูปแบบข้อความได้ที่:

https://github.com/scottbw/dialoguejs

มันไม่รองรับเงื่อนไขหรือทริกเกอร์เหตุการณ์ (ยัง) แต่อาจง่ายพอที่จะเริ่มต้นด้วย devs เกมจำนวนมาก

(รหัสตัวเองใน GPL, btw)


คำถามถามหา C #
เซทแบททิน

D'oh - ขอโทษด้วย
Scott Wilson
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.