การค้นหาอัลกอริธึม


24

ฉันโพสต์คำถามนี้ใน stack overflow ก่อน แต่ฉันคิดว่าไม่มีใครสนใจวิดีโอเกมที่นั่น ...

เส้นทางการค้นหาอัลกอริทึมในเกมทุกประเภทมีอะไรบ้าง (ในทุกประเภทที่มีการเคลื่อนไหวของตัวละครอยู่ดี) Dijkstra ใช้ของเยอะใช่มั้ย ฉันคิดว่าไม่เพราะมันไม่ได้ทำตามขั้นตอนเพื่อไปไหนสักแห่งใช่ไหม? ถ้าฉันเข้าใจถูกต้องมันจะกำหนดเฉพาะวัตถุที่ใกล้ที่สุด ฉันไม่ได้ต้องการโค้ดอะไรเลย เพียงแค่ทำการวิจัยบางอย่างแม้ว่าคุณจะวาง pseudocode หรืออะไรบางอย่างที่จะดี (ฉันสามารถเข้าใจ Java และ C ++) โดยทั่วไปฉันกำลังมองหาภาพรวมอย่างรวดเร็วของการค้นหาเส้นทางโดยทั่วไป

ฉันรู้ว่า A * เป็นเหมือนอัลกอริทึมที่ใช้ในเกม 2D นั่นยอดเยี่ยมและทั้งหมด แต่เกมแบบ 2D ที่ไม่อิงกับกริดเป็นอย่างไร สิ่งต่าง ๆ เช่น Age of Empires หรือ Link's Awakening ไม่มีช่องว่างสี่เหลี่ยมที่แตกต่างกันในการนำทางดังนั้นพวกเขาจะทำอย่างไร

เกม 3 มิติทำอะไรได้บ้าง ฉันได้อ่านสิ่งนี้แล้วhttp://www.ai-blog.net/archives/000152.htmlซึ่งฉันได้ยินว่าเป็นผู้มีอำนาจยิ่งใหญ่ในเรื่องนี้ แต่มันก็ไม่ได้อธิบายวิธีการจริงๆเมื่อมีการตั้งเครือข่าย การค้นหาเส้นทางเสร็จสิ้น หากใช้ A * เป็นสิ่งที่ใช้แล้วจะมีวิธีการอย่างไรในสภาพแวดล้อม 3 มิติ และเดือยจะทำงานอย่างไรสำหรับการปัดเศษมุม?


2
ฉันคิดว่าคำถามนี้เปิดกว้างเกินไปสำหรับรูปแบบคำถามและคำตอบของ SE คำถามที่พบบ่อย
John McDonald

1
เกมที่คุณกล่าวถึงจะต้องแบ่งแผนที่เป็นโหนดสำหรับ A * ไม่ทางใดก็ทางหนึ่ง กระบวนการแยกย่อยนั้นไม่จำเป็นต้องเกี่ยวข้องกับกริดสแควร์และมีหลายวิธีที่จะทำได้ตรวจสอบ vid youtube.com/watch?v=nGC_kBCoHYcเกมที่ดีทำให้ผู้เล่นไม่สามารถบอกได้ว่าพวกเขากำลังทำอะไร จริง ๆ แล้วทำอยู่เบื้องหลัง
XiaoChuan Yu

1
มีคำถามมากมายที่นี่ดังนั้นฉันจึงไม่สามารถเขียนคำตอบได้จริงๆ แต่ฉันจะทราบว่า Dijkstra กลับเส้นทางและอัลกอริธึมการค้นหาเส้นทางส่วนใหญ่เป็นแบบอเนกประสงค์ คุณแปลงโลกของคุณ 2D หรือ 3D เป็นกราฟที่เชื่อมต่อและเรียกใช้อัลกอริทึมการค้นหาเส้นทางบนมัน
Gregory Avery-Weir

เพียงสำหรับการอ้างอิง: ผมได้ตอบคำถามที่แตกมากเกิน
Julian

1
อนุญาตให้ฉันพูดจาโผงผาง คำถามนี้มี 4 upvotes บน SO เมื่อเทียบกับ 4 votes ที่ใกล้เคียงกับ GDSE ฉันอดไม่ได้ที่จะรู้สึกว่าผู้ดูแลเว็บไซต์นี้ก้าวร้าวมากเกินไป แน่นอนว่าฉันสามารถดูว่าคำถามนั้นขัดกับหลักเกณฑ์ที่ระบุในคำถามที่พบบ่อย แต่อ้างถึงแนวทางเหล่านั้นเพื่อป้องกันไม่ให้เกิดdiminishing the usefulness of our siteขึ้น คำถามนี้ได้รับการสนับสนุน 3 ครั้งแล้วซึ่งเป็นข้อพิสูจน์ว่าเป็นประโยชน์กับผู้ใช้บางคน ดังนั้นฉันจึงอดไม่ได้ที่จะรู้สึกว่าการลงคะแนนเพื่อปิดและเสี่ยงต่อการถูกถอดถอนในที่สุดก็เป็นสิ่งที่ต่อต้านได้มากกว่า
David Gouveia

คำตอบ:


62

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


ส่วนที่ 1 - อัลกอริทึมการทำให้เข้าใจผิด

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

  • วิธีการดั้งเดิมที่ไม่ "มองไปข้างหน้า" และทำทีละขั้นตอน:

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

    • Obstacle tracing - วิธีอื่น ๆ คล้ายกับ backstepping แบบสุ่ม แต่แทนที่จะเคลื่อนที่กลับแบบสุ่มให้เริ่มการติดตามรอบ ๆ วัตถุเมื่อพบการชนราวกับว่าคุณมีมือขวาติดอยู่กับกำแพงและต้องขยับสัมผัส เมื่อไม่มีการชนกันอย่างต่อเนื่องเคลื่อนที่ไปในทิศทางของเป้าหมาย อีกครั้งสามารถติดในหลาย ๆ สถานการณ์

  • วิธีการที่มองไปข้างหน้าเพื่อค้นหาเส้นทางทั้งหมดในครั้งเดียว:

    • การค้นหาครั้งแรกกว้าง - สำรวจกราฟอย่างง่ายโดยไปที่ชั้นของเด็กแต่ละครั้งหยุดเมื่อพบเส้นทาง หากกราฟไม่มีการถ่วงน้ำหนัก (เช่นระยะห่างระหว่างแต่ละโหนดที่อยู่ติดกันจะเท่ากันเสมอ) จะพบเส้นทางที่สั้นที่สุดแม้ว่าจะไม่ได้ประสิทธิภาพมากเกินไป สำหรับกราฟที่มีน้ำหนักถ่วงน้ำหนักมันอาจไม่ส่งคืนพา ธ ที่สั้นที่สุด แต่จะหาได้หากมีอยู่

    • การค้นหาความลึกครั้งแรก - อีกวิธีหนึ่งในการสำรวจกราฟ แต่แทนที่จะเอามันเป็นชั้น ๆ เลเยอร์อัลกอริทึมจะพยายามค้นหาลึกลงไปในกราฟก่อน วิธีนี้อาจมีปัญหาหากความลึกของการค้นหาไม่ จำกัด โดยเฉพาะอย่างยิ่งเมื่อใช้การใช้งานแบบเรียกซ้ำซึ่งอาจนำไปสู่การโอเวอร์โฟลว์สแต็กดังนั้นจึงมักจะปลอดภัยกว่าในการติดตั้งซ้ำ ๆ

    • การค้นหาครั้งแรกที่ดีที่สุด - คล้ายกับการค้นหาแบบกว้างครั้งแรก แต่ใช้การวิเคราะห์พฤติกรรมที่เลือกเพื่อนบ้านที่มีแนวโน้มมากที่สุดก่อน เส้นทางที่ส่งคืนอาจไม่สั้นที่สุด แต่จะเร็วกว่าการค้นหาแบบกว้างครั้งแรก A * เป็นประเภทของการค้นหาครั้งแรกที่ดีที่สุด

    • วิธีการของ Dijkstra - ติดตามค่าใช้จ่ายทั้งหมดตั้งแต่เริ่มต้นจนถึงทุกโหนดที่เข้าชมและใช้เพื่อกำหนดลำดับที่ดีที่สุดในการสำรวจกราฟ ทำงานกับกราฟถ่วงน้ำหนักและส่งคืนเส้นทางที่สั้นที่สุด แต่อาจเกี่ยวข้องกับการค้นหาจำนวนมาก

    • A * - คล้ายกับ Dijkstra แต่ใช้ฮิวริสติกเพื่อประเมินความเป็นไปได้ที่แต่ละโหนดจะใกล้เคียงกับเป้าหมายเพื่อที่จะทำการตัดสินใจที่ดีที่สุด ด้วยเหตุนี้ฮิวริสติก A จึงค้นหาเส้นทางที่สั้นที่สุดในกราฟถ่วงน้ำหนักในเวลาที่เหมาะสมกว่า

  • จากนั้นจะมีการเปลี่ยนแปลงของ A * (หรือการปรับแต่งการหาเส้นทางโดยทั่วไป) ที่ทำให้มันเร็วขึ้นหรือปรับให้เข้ากับสภาพแวดล้อมบางอย่างเช่น (ดูคำตอบที่เกี่ยวข้องและรายการที่ครอบคลุมใน cstheory.SE ):

    • LPA * - คล้ายกับ A * แต่สามารถคำนวณเส้นทางที่ดีที่สุดได้อย่างรวดเร็วยิ่งขึ้นเมื่อมีการเปลี่ยนแปลงกราฟเล็กน้อย
    • D * Lite - ขึ้นอยู่กับ LPA * มันทำสิ่งเดียวกัน แต่สมมติว่า "จุดเริ่มต้น" เป็นหน่วยเคลื่อนที่ไปสู่เส้นชัยในขณะที่มีการเปลี่ยนแปลงกราฟ
    • HPA * (ลำดับชั้น) - ใช้หลายเลเยอร์ที่ระดับ abstraction ที่แตกต่างกันเพื่อเพิ่มความเร็วในการค้นหา ยกตัวอย่างเช่นเลเยอร์เลเวลที่สูงกว่านั้นอาจเชื่อมต่อห้องต่างๆในขณะที่เลเยอร์เลเยอร์ที่ต่ำกว่าจะคอยดูแลหลีกเลี่ยงอุปสรรค
    • IDA * (Iterative Deepening) - ลดการใช้หน่วยความจำโดยเปรียบเทียบกับ A * ปกติโดยใช้การทำซ้ำลึก
    • SMA * (ขอบเขตของหน่วยความจำแบบง่าย) - ใช้เฉพาะหน่วยความจำที่มีอยู่เพื่อดำเนินการค้นหา
    • ค้นหาจุดกระโดด - มอบเครดิตให้แก่ Eric ในการแสดงความคิดเห็นเพื่อพูดถึงมัน! เพิ่มความเร็วการค้นหาเส้นทางบนแผนที่กริดต้นทุนสม่ำเสมอ ( ลิงค์ )

ส่วนที่ 2 - การแทน Space Search

และสุดท้ายเพื่อตอบคำถามนี้:

ฉันรู้ว่า A * เป็นเหมือนอัลกอริทึมที่ใช้ในเกม 2D นั่นยอดเยี่ยมและทั้งหมด แต่เกมแบบ 2D ที่ไม่อิงกับกริดเป็นอย่างไร

ความเข้าใจผิดครั้งใหญ่สองประการที่นี่! ในความเป็นจริง:

  1. A * ไม่สนใจว่าเกมนั้นเป็น 2D หรือ 3D และมีความเหมาะสมเท่าเทียมกันสำหรับทั้งสองกรณี
  2. A * ทำงานภายใต้การแสดงกราฟใด ๆดังนั้นจึงไม่สนใจว่าโลกจะเป็นกริดหรือไม่

ดังนั้นหากโลกไม่จำเป็นต้องเป็นกริดคุณสามารถเป็นตัวแทนในรูปแบบอื่นได้อีกบ้าง? ต่อไปนี้เป็นภาพรวมโดยย่อเกี่ยวกับวิธีแบ่งพาร์ติชันของพื้นที่โลกสำหรับการหาเส้นทางและส่วนใหญ่ของงานเหล่านี้ทั้งสำหรับ 2D และ 3D:

  • Rectangular grid - แบ่งพาร์ติชันออกเป็นกริดสแควร์ปกติโดยแต่ละเซลล์ในกริดนั้นเป็นหนึ่งโหนดในกราฟและการเชื่อมต่อระหว่างสองโหนดที่ไม่มีสิ่งกีดขวางนั้นเป็นขอบ

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

  • Quadtree - อีกวิธีในการแบ่งพื้นที่ แต่แทนที่จะแบ่งพาร์ติชันเป็นกริดของเซลล์ที่มีขนาดปกติให้แบ่งพาร์ติชันเป็นสี่พาร์ติชันแล้วแบ่งพาร์ติชันเหล่านี้ออกเป็นสี่ส่วนอีกครั้ง เพิ่มมิติที่สามทำให้octree

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

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

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

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

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


1
สองลิงก์: 1) Mikko Mononenได้ทำเส้นทางหางานKillzone 3และเขามีบล็อกที่ดีมากที่เขาบันทึกกระบวนการพัฒนาของ Recast (เครื่องมือสร้าง navmesh) และ Detour (เครื่องมือค้นหาเส้นทาง) ทั้งภายใต้ใบอนุญาต MIT และใช้เป็นตัวอย่าง ในKingdoms of Amalur: Reckoning 2) การค้นหาจุดกระโดดคือฉันคิดว่าเป็นหนึ่งในพัฒนาการล่าสุดที่ใหญ่ที่สุดในการค้นหาเส้นทางแบบอิงกริด
เอริค
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.