มีความแตกต่างอย่างมากระหว่างกลไกการชนกับเครื่องยนต์ฟิสิกส์ พวกเขาไม่ได้ทำสิ่งเดียวกันแม้ว่าโดยทั่วไปแล้วเครื่องมือฟิสิกส์จะอาศัยกลไกการชน
เอ็นจินการชนกันจะถูกแบ่งออกเป็นสองส่วน: การตรวจจับการชนและการตอบสนองการชน ส่วนหลังเป็นส่วนหนึ่งของเครื่องยนต์ฟิสิกส์ นี่คือสาเหตุที่กลไกการชนและเครื่องยนต์ฟิสิกส์มักจะถูกนำไปไว้ในห้องสมุดเดียวกัน
การตรวจจับการชนมาในสองรูปแบบโดยสิ้นเชิงและต่อเนื่อง เอ็นจิ้นขั้นสูงรองรับทั้งสองเนื่องจากมีคุณสมบัติแตกต่างกัน โดยทั่วไปการตรวจจับการชนกันอย่างต่อเนื่องมีราคาแพงมากและใช้เฉพาะเมื่อจำเป็นเท่านั้น การชนกันส่วนใหญ่และฟิสิกส์ได้รับการจัดการโดยใช้วิธีการที่ไม่ต่อเนื่อง ในวิธีการที่ไม่ต่อเนื่องวัตถุจะจบลงด้วยการเจาะเข้าหากันและจากนั้นเครื่องยนต์ฟิสิกส์ก็ทำงานเพื่อแยกพวกมันออกจากกัน ดังนั้นเครื่องยนต์ไม่ได้หยุดผู้เล่นจากการเดินผ่านกำแพงหรือพื้นเพียงบางส่วนมันเพิ่งซ่อมมันขึ้นหลังจากตรวจพบว่าผู้เล่นบางส่วนอยู่ในกำแพง / พื้น ฉันจะมุ่งเน้นไปที่การตรวจจับการชนแบบไม่ต่อเนื่องที่นี่เพราะนั่นคือสิ่งที่ฉันมีประสบการณ์มากที่สุดในการดำเนินการตั้งแต่เริ่มต้น
ตรวจจับการชนกัน
การตรวจจับการชนนั้นค่อนข้างง่าย วัตถุทุกชิ้นมีการแปลงและรูปร่าง (อาจมีหลายรูปร่าง) แนวทางไร้เดียงสาจะมีเอ็นจินการชนกันทำลูป O (n ^ 2) ผ่านคู่วัตถุทั้งหมดและทดสอบว่ามีการทับซ้อนกันระหว่างคู่ ในแนวทางที่ชาญฉลาดจะมีโครงสร้างข้อมูลเชิงพื้นที่จำนวนมาก (เช่นสำหรับวัตถุคงที่เทียบกับวัตถุแบบไดนามิก) รูปร่างที่มีขอบเขตสำหรับแต่ละวัตถุและรูปร่างย่อยส่วนนูนหลายส่วนสำหรับแต่ละวัตถุ
โครงสร้างข้อมูลเชิงพื้นที่ประกอบด้วยสิ่งต่าง ๆ เช่น KD-Trees, Dynamic AABB trees, Octrees / Quadtrees, Binary Space Partitioning tree และอื่น ๆ แต่ละอันมีข้อดีและข้อเสียซึ่งเป็นสาเหตุที่เอ็นจิ้นเอนด์ที่สูงกว่าบางอันใช้มากกว่าหนึ่ง ยกตัวอย่างเช่นต้นไม้ AABB แบบไดนามิกนั้นเร็วและดีจริง ๆ สำหรับการจัดการกับวัตถุที่เคลื่อนไหวจำนวนมากในขณะที่ KD-Tree อาจเหมาะสมกว่าสำหรับรูปทรงเรขาคณิตระดับคงที่ที่วัตถุชนกัน มีตัวเลือกอื่น ๆ เช่นกัน
ระยะกว้างใช้โครงสร้างข้อมูลเชิงพื้นที่และปริมาณขอบเขตนามธรรมสำหรับแต่ละวัตถุ ไดรฟ์ข้อมูลขอบเขตเป็นรูปร่างง่าย ๆ ที่ล้อมรอบวัตถุทั้งหมดโดยทั่วไปโดยมีเป้าหมายในการล้อมรอบวัตถุนั้นว่า "แน่น" ที่สุดเท่าที่จะเป็นไปได้ในขณะที่เหลือราคาถูกเพื่อทำการทดสอบการชน รูปร่างที่ถูกล้อมรอบที่พบมากที่สุดคือกล่องที่ถูกจัดแนวตามแนวแกน, กล่องที่ถูกจัดแนวตามวัตถุ, ทรงกลมและแคปซูล โดยทั่วไปแล้ว AABBs จะถือว่าเร็วที่สุดและง่ายที่สุด (Spheres นั้นง่ายกว่าและเร็วกว่าในบางกรณี แต่โครงสร้างข้อมูลเชิงพื้นที่จำนวนมากนั้นต้องการการเปลี่ยนทรงกลมเป็น AABB ต่อไป) แต่ก็มีแนวโน้มที่จะบรรจุวัตถุจำนวนมากได้ไม่ดี แคปซูลเป็นที่นิยมในเอนจิ้น 3 มิติสำหรับการจัดการการชนระดับตัวละคร เครื่องมือบางอย่างจะใช้รูปร่างสองขอบเขต
ขั้นตอนสุดท้ายของการตรวจจับการชนกันคือการตรวจสอบว่าที่เรขาคณิตตัดกัน สิ่งนี้มักแสดงถึงการใช้ตาข่าย (หรือรูปหลายเหลี่ยมในแบบ 2D) แต่อาจไม่เสมอไป จุดประสงค์ของระยะนี้คือการตรวจสอบว่าวัตถุจริง ๆ ทำการชนกันหรือไม่หากต้องการรายละเอียดในระดับที่ดี (เช่นการชนกระสุนในปืนซึ่งคุณต้องการที่จะไม่สนใจภาพที่เพิ่งจะพลาด) และ นอกจากนี้เพื่อค้นหาว่าวัตถุใดที่ชนกันซึ่งจะส่งผลต่อการตอบสนองของวัตถุ ตัวอย่างเช่นหากกล่องกำลังนั่งอยู่บนขอบของตารางเครื่องยนต์จะต้องรู้ว่าสิ่งที่จุดตารางจะผลักดันกับกล่อง; ขึ้นอยู่กับว่ากล่องนั้นห้อยอยู่นานแค่ไหนกล่องนั้นอาจเริ่มเอียงและร่วงหล่น
ติดต่อ Manifold Generation
อัลกอริทึมที่ใช้ในที่นี้รวมถึงอัลกอริธึมการปรับแต่งพอร์ทัลยอดนิยมของ GJK และ Minkowski รวมถึงการทดสอบแกนแยก เนื่องจากอัลกอริทึมยอดนิยมมักใช้งานได้กับรูปร่างนูนเท่านั้นจึงจำเป็นต้องแยกวัตถุที่ซับซ้อนหลายอย่างออกเป็นวัตถุย่อยนูนและทำการทดสอบการชนกันของแต่ละวัตถุ นี่คือหนึ่งในเหตุผลที่ทำให้การใช้งานตาข่ายแบบง่ายสำหรับการชนรวมถึงการลดเวลาในการประมวลผลสำหรับการใช้สามเหลี่ยมน้อยลง
อัลกอริทึมเหล่านี้บางส่วนไม่เพียง แต่บอกคุณว่าวัตถุชนกันอย่างแน่นอน แต่ที่ใดที่มันชนกัน - พวกมันจะเจาะทะลุกันได้ไกลแค่ไหน อัลกอริทึมบางตัวต้องการขั้นตอนเพิ่มเติมเช่นการตัดรูปหลายเหลี่ยมเพื่อรับข้อมูลนี้
การตอบสนองทางกายภาพ
ณ จุดนี้ผู้ติดต่อถูกค้นพบและมีข้อมูลเพียงพอสำหรับเอนจินฟิสิกส์ที่จะประมวลผลผู้ติดต่อ การจัดการทางฟิสิกส์นั้นซับซ้อนมาก อัลกอริทึมที่เรียบง่ายใช้งานได้สำหรับเกมบางเกม แต่แม้กระทั่งบางสิ่งที่ดูเหมือนตรงไปตรงมาเช่นเดียวกับการรักษากล่องให้คงที่กลายเป็นเรื่องยากและต้องใช้งานจำนวนมากและการแฮ็กที่ไม่ชัดเจน
ในระดับพื้นฐานที่สุดเอ็นจิ้นฟิสิกส์จะทำสิ่งนี้: มันจะนำวัตถุที่ชนกันและรายชื่อผู้ติดต่อของพวกเขาและคำนวณตำแหน่งใหม่ที่จำเป็นในการแยกวัตถุที่ชนกัน มันจะย้ายวัตถุไปยังตำแหน่งใหม่เหล่านี้ นอกจากนี้ยังจะคำนวณการเปลี่ยนแปลงความเร็วที่เกิดจากการกดนี้รวมกับการซ่อมแซม (ค่า bounciness) และค่าความเสียดทาน เครื่องยนต์ฟิสิกส์จะใช้แรงอื่น ๆ ที่กระทำกับวัตถุเช่นแรงโน้มถ่วงเพื่อคำนวณความเร็วใหม่ของวัตถุและจากนั้น (เฟรมถัดไป) ตำแหน่งใหม่ของพวกเขา
การตอบสนองทางฟิสิกส์ขั้นสูงมากขึ้นซับซ้อนขึ้นอย่างรวดเร็ว วิธีการข้างต้นจะพังทลายลงในหลาย ๆ สถานการณ์รวมถึงวัตถุหนึ่งวางอยู่บนอีกสองคน การจัดการกับแต่ละคู่ด้วยตัวเองจะทำให้ "กระวนกระวายใจ" และวัตถุจะเด้งไปรอบ ๆ เทคนิคพื้นฐานที่สุดคือการทำซ้ำการแก้ไขความเร็วจำนวนคู่ของวัตถุที่ชนกัน ตัวอย่างเช่นเมื่อมีกล่อง "A" นั่งอยู่ด้านบนของอีกสองกล่อง "B" และ "C" การชนกันของข้อมูล AB จะได้รับการจัดการก่อนทำให้กล่อง A เอียงต่อไปในกล่อง C จากนั้นจัดการกับการชน AC ตอนเย็น ออกกล่องบ้าง แต่ดึง A ลงไปและ B จากนั้นทำซ้ำอีกครั้งดังนั้นข้อผิดพลาด AB ที่เกิดจากการแก้ไข AC จะได้รับการแก้ไขเล็กน้อยทำให้เกิดข้อผิดพลาดเล็กน้อยในการตอบสนอง AC ซึ่งจัดการเมื่อ AC ถูกประมวลผลอีกครั้ง จำนวนการวนซ้ำที่ทำขึ้นนั้นไม่คงที่และไม่มีจุดใดที่จะกลายเป็น "สมบูรณ์แบบ" แต่จะวนซ้ำทุกครั้งที่หยุดให้ผลลัพธ์ที่มีความหมาย การวนซ้ำ 10 ครั้งเป็นครั้งแรกโดยทั่วไป แต่ต้องใช้การปรับแต่งตัวเลขที่ดีที่สุดสำหรับเอ็นจิ้นเฉพาะและความต้องการของเกม
ติดต่อแคช
มีเทคนิคอื่น ๆ ที่มีประโยชน์มาก (จำเป็นหรือมากน้อยกว่า) เมื่อต้องรับมือกับเกมหลายประเภท การแคชผู้ติดต่อเป็นหนึ่งในสิ่งที่มีประโยชน์มากกว่า ด้วยแคชผู้ติดต่อแต่ละชุดของการชนกันของวัตถุจะถูกบันทึกไว้ในตารางการค้นหา แต่ละเฟรมเมื่อตรวจพบการชนแคชนี้จะถูกสอบถามเพื่อดูว่าวัตถุนั้นเคยถูกสัมผัสมาก่อนหรือไม่ หากวัตถุไม่เคยสัมผัสมาก่อนสามารถสร้างเหตุการณ์ "การชนกันใหม่" หากวัตถุที่เคยสัมผัสมาก่อนหน้านี้สามารถใช้ข้อมูลเพื่อให้การตอบสนองที่เสถียรยิ่งขึ้น รายการใด ๆ ในแคชผู้ติดต่อที่ไม่ได้อัพเดตในเฟรมจะระบุวัตถุสองอย่างที่แยกออกจากกันและสามารถสร้างเหตุการณ์ "แยกวัตถุ" ได้ ตรรกะของเกมมักจะใช้สำหรับเหตุการณ์เหล่านี้
นอกจากนี้ยังเป็นไปได้ที่ตรรกะของเกมจะตอบสนองต่อเหตุการณ์การปะทะกันใหม่และตั้งค่าสถานะเป็นไม่สนใจ สิ่งนี้มีประโยชน์จริง ๆ สำหรับการใช้งานคุณสมบัติบางอย่างที่พบได้ทั่วไปในแพลตฟอร์มเช่นแพลตฟอร์มที่คุณสามารถข้ามไปได้ การใช้งานที่ไร้เดียงสาอาจเพิกเฉยต่อการชนที่มีการชนกันของแพลตฟอร์ม -> การชนกันของตัวละครปกติ (ระบุหัวของผู้เล่นที่ถูกกระแทกที่ด้านล่างของแพลตฟอร์ม) แต่หากไม่มีการแคชที่ติดต่อ จะลดลง. ณ จุดนั้นผู้ติดต่อปกติอาจสิ้นสุดการชี้ขึ้นไปด้านบนทำให้ผู้เล่นปรากฏขึ้นบนแพลตฟอร์มเมื่อเขาไม่ควรทำ ด้วยการแคชผู้ติดต่อเครื่องยนต์สามารถดูการชนเริ่มต้นตามปกติได้อย่างน่าเชื่อถือและไม่สนใจเหตุการณ์การติดต่อต่อไปทั้งหมดจนกว่าแพลตฟอร์มและผู้เล่นจะแยกกันอีกครั้ง
นอนหลับ
อีกเทคนิคที่มีประโยชน์มากคือการทำเครื่องหมายวัตถุว่า "หลับ" หากพวกเขาไม่ได้ถูกโต้ตอบด้วย วัตถุการนอนหลับไม่ได้รับการปรับปรุงทางฟิสิกส์อย่าชนกับวัตถุการนอนหลับอื่น ๆ และโดยทั่วไปเพียงแค่นั่งอยู่ตรงนั้นในเวลาจนกว่าวัตถุที่ไม่ได้นอนหลับอื่นจะชนกับวัตถุเหล่านั้น
ผลกระทบคือทั้งคู่ของวัตถุที่กำลังชนกันซึ่งกำลังนั่งอยู่ที่นั่นไม่ทำอะไรเลยไม่ต้องใช้เวลาในการประมวลผล นอกจากนี้เนื่องจากไม่มีการแก้ไขฟิสิกส์เล็กน้อยอย่างต่อเนื่องสแต็คจะเสถียร
วัตถุเป็นตัวเลือกในการนอนหลับเมื่อมันมีความเร็วใกล้ศูนย์มากกว่าหนึ่งเฟรม โปรดทราบว่า epsilon ที่คุณใช้สำหรับทดสอบความเร็วใกล้ศูนย์นี้อาจจะสูงกว่า epsilon เปรียบเทียบกับจุดลอยตามปกติเล็กน้อยเนื่องจากคุณควรคาดหวังว่า jitter ที่มีวัตถุซ้อนกันและคุณต้องการให้วัตถุทั้งกองนอนหลับหากพวกเขา ' กำลังพัก "ใกล้พอ" ถึงมั่นคง แน่นอนว่าเกณฑ์จะต้องมีการปรับแต่งและการทดลอง
ข้อ จำกัด
บิตหลักสุดท้ายของเอนจินฟิสิกส์จำนวนมากคือตัวแก้ข้อ จำกัด วัตถุประสงค์ของระบบดังกล่าวคือเพื่ออำนวยความสะดวกในการดำเนินการต่างๆเช่นสปริง, มอเตอร์, แกนล้อ, ตัวอ่อนจำลอง, ผ้า, เชือกและโซ่และบางครั้งก็เป็นของไหล (แม้ของเหลวจะถูกนำมาใช้เป็นระบบที่แตกต่างกันโดยสิ้นเชิง)
แม้แต่พื้นฐานของการแก้ปัญหาข้อ จำกัด ก็ยังสามารถเรียนรู้คณิตศาสตร์ได้อย่างเข้มข้นและก้าวข้ามความเชี่ยวชาญของฉันในเรื่องนี้ ฉันขอแนะนำให้ตรวจสอบชุดบทความที่ยอดเยี่ยมของ Randy Gaul เกี่ยวกับฟิสิกส์สำหรับคำอธิบายเชิงลึกเพิ่มเติมของหัวข้อ