วิธีทำให้ตัวละครของฉันลื่นไหลขณะเดินบนเส้นทาง (รายการพิกัด)


15

ฉันมีรายการที่มีพิกัด - เอาต์พุตจากอัลกอริทึม A * และฉันต้องการทำให้ตัวละครของฉันเดินตามเส้นทางนี้อย่างราบรื่นด้วยการหมุน

ดังนั้นฉันมีบางอย่างเช่นAและฉันต้องการได้C

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

ฉันจะทำสิ่งนี้ได้อย่างไร

แก้ไข

หากต้องการทำให้ตัวเองชัดเจนยิ่งขึ้น:

ฉันสนใจที่จะหมุนอย่างราบรื่นมากขึ้นเนื่องจากฉันรู้วิธีการเดินจากโหนดหนึ่งไปอีกโหนดหนึ่ง

แก้ไข

หลายคนพบว่ามีประโยชน์ (ฉันด้วย) ฉันกำลังโพสต์ลิงก์ไปยัง "ธรรมชาติของรหัส" ของ Daniel Shiffman ซึ่งเขาพูดถึงปัญหา AI (และฟิสิกส์) ของเกมเช่นปัญหาพฤติกรรมพวงมาลัยhttp://natureofcode.com/book/chapter- 6 อิสระตัวแทน / # chapter06_section8


การสร้างเส้นทางใน Unity ไม่ได้ใช่หรือไม่
joltmode

@Tom ใช่ แต่ฉันมีรุ่นของฉันดำเนินการอยู่แล้ว ประเด็นของคำถามนี้คือการหมุนอย่างราบรื่น (การหมุน) ในขณะที่เดินบนเส้นทาง
Patryk

3
คำที่ดีสำหรับ Google ในเรื่องนี้คือ 'พฤติกรรมการเคลื่อนไหว' :)
รอยต.

3
@RoyT แน่นอน ! ฉันได้อ่านเมื่อไม่กี่สัปดาห์ที่ผ่านมาและลืมไปแล้ว: / นี่เป็นบทความที่ยอดเยี่ยมเกี่ยวกับเส้นทางที่มีคำอธิบายทางคณิตศาสตร์และฟิสิกส์ที่ยอดเยี่ยม natureofcode.com
Patryk

1
ฉันแค่อยากจะขอบคุณ @Patryk สำหรับลิงก์ - ดูเป็นข้อมูลจริงๆและฉันค้นหาแหล่งข้อมูลที่ดีเกี่ยวกับพฤติกรรมการหมุนพวงมาลัย
คริสเตียน

คำตอบ:


7

หากคุณต้องการเส้นทางที่ราบรื่นในสภาพแวดล้อมแบบเรียงต่อกันจะไม่มีวิธีแก้ไขการปรับเส้นทางให้เรียบในจุด A * ของคุณ ในหนังสือของเขาเกี่ยวกับการเขียนโปรแกรมเกม AI, Matt Buckland อธิบายอัลกอริทึมที่ง่ายและรวดเร็วในการทำให้เส้นทางเรียบ (โดยทั่วไปลบขอบทั้งหมดที่สามารถลบออกได้

เมื่อคุณลบขอบที่ไม่จำเป็นออกไปเช่นนี้กรณีแรกของคุณ ( A -> B ) จะถูกแก้ไข การทำให้ขอบในกราฟของคุณเรียบออกสามารถทำได้หลายวิธี เป็นไปได้มากว่าHermite splinesจะใช้ได้ (ขึ้นอยู่กับความหนาแน่นของสิ่งกีดขวางและขนาดของกระเบื้อง) ตัวเลือกอื่นอาจเป็นพฤติกรรมการบังคับเลี้ยวที่คุณเริ่มหันไปทางจุดต่อไปทันทีที่คุณออกไปครึ่งแผ่นจากเป้าหมายปัจจุบัน


9

ดังที่คนอื่น ๆ ได้กล่าวไว้สำหรับกรณีที่สองคุณจะต้องใช้ spline แบบใดแบบหนึ่งหรือ (จริง ๆ แล้วเป็นแบบที่ดีกว่าสำหรับตัวอย่างของคุณ) ให้หน่วยพฤติกรรมการหมุนพวงมาลัย

อย่างไรก็ตามสำหรับกรณีแรกมีวิธีแก้ปัญหาที่ง่ายกว่าและให้ผลลัพธ์ที่ดีกว่าการทำให้เส้นทางเรียบ มันเรียกว่าTheta *และเป็นส่วนขยายที่ง่าย(และค่อนข้างใหม่)ของ A * บนกริดที่อนุญาตให้หน่วยเคลื่อนที่ในทิศทางใดก็ได้ระหว่างจุดตาราง

เธต้า * กับการทำให้เส้นทางเรียบ

มีบทความที่ดีอธิบาย Theta * (ซึ่งฉันขโมยภาพด้านบน) ที่นี่


2

เพื่อการเคลื่อนไหวที่สมจริงยิ่งขึ้นของมนุษย์ลองผสมผสานกับพฤติกรรมของพวงมาลัย (รุ่น C # ของ OpenSteer คลาสสิกhttp://sharpsteer.codeplex.com/ ) คุณได้ผลลัพธ์ของ AStar และให้พฤติกรรมการหมุนพวงมาลัยนั้นเกี่ยวกับการเคลื่อนที่ (หนึ่งในตัวอย่างแสดงวิธีการทำอย่างแม่นยำนำทางไปตามเส้นทาง)


1

ในกรณีการนำทางจากจุดหนึ่งไปยังอีกจุดหนึ่งฉันใช้ความแตกต่างของมุม (ทิศทางผู้เล่นปัจจุบันเทียบกับทิศทางจากจุดปัจจุบันไปยังจุดต่อไป) จากนั้นค่อย ๆ เปลี่ยนมุมเป็นมุมสุดท้ายเมื่อการเคลื่อนไหวเกิดขึ้น ตรวจสอบเกมนี้ที่นี่โดยที่เครื่องบินเคลื่อนที่จากจุดหนึ่งไปยังอีกจุดหนึ่ง แต่การเลี้ยวนั้นไม่ได้เกิดขึ้นอย่างฉับพลัน แต่เมื่อดูอย่างละเอียดคุณสามารถระบุจุดของเส้นทางได้ (เกมใช้งานได้บนมือถือโดยเฉพาะ iPhone / iPad)


ตรงนี้เป็นสิ่งที่ฉันทำ
Patryk

1

ฉันโชคดีมากกับCatmull-Rom splines (ลูกบาศก์ชนิดหนึ่งตามที่แนะนำโดย @bummzack) ส่วนที่ดีเกี่ยวกับสิ่งเหล่านั้นก็คือเส้นโค้งจะผ่านจุดควบคุมเสมอคนอื่น ๆ ไม่ทำเช่นนั้น ใช้สิ่งนี้:

t    = <time*>
t12  = t + 1.0
t23  = t
t34  = t - 1.0
t123 = (t + 1.0) / 2.0
t234 = t / 2

c1 = controlpoint[0];
c2 = controlpoint[1];
c3 = controlpoint[2];
c4 = controlpoint[3];

l12 = lerp(c1, c2, t12);
l23 = lerp(c2, c3, t23);
l34 = lerp(c3, c4, t34);
position = lerp(lerp(l12, l23, t123), lerp(l23, l34, t234), t);

* timeคือค่า [0,1] ระหว่างจุดควบคุม 1 และ 2


0

A-> B สามารถแก้ไขได้โดยการใช้ตาข่ายนำทางแทนที่จะเป็นกริด สิ่งนี้แสดงถึงการเปลี่ยนแปลงครั้งใหญ่ในการสร้างข้อมูลการค้นหาเส้นทาง

กรณีเช่น C และ D เป็นเพียงการตัดมุม: หากตัวละครกำลังเคลื่อนที่ในเส้นทางและภายใน "มุม" (เซลล์ที่ก่อนหน้าปัจจุบันเซลล์ถัดไปไม่ได้อยู่ในแนวเส้นตรง) ให้กดไปในทิศทางของเซลล์ทั้งก่อนหน้าและถัดไป . ปัญหาเดียวคือการกำหนดระยะทางจากตำแหน่งจริง (ระยะทางผลัก) ซึ่งอาจต้องใช้ระยะทางจากเซลล์ปัจจุบันเป็นอินพุต บางสิ่งเช่นนี้

push_dir = average( prevcell.pos, nextcell.pos ) - curcell.pos;
push_dist = cell_half_width - distance( char.pos, curcell.pos );
char.pos += push_dir * push_dist;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.