โมเมนตัมและลำดับของปัญหาการอัพเดทในเอนจิ้นฟิสิกส์ของฉัน


22

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

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


หากคุณไม่ต้องการอ่านคำถามก่อนหน้านี่เป็นคำอธิบายสั้น ๆ เกี่ยวกับการทำงานของเครื่องมือฟิสิกส์ของฉัน:

ทุกหน่วยงานทางกายภาพจะถูกเก็บไว้ในคลาสที่เรียกว่า SSSPBody

รองรับเฉพาะ AABB

SSSPBody ทุกคนถูกเก็บไว้ในคลาสที่เรียกว่า SSSPWorld ซึ่งจะอัปเดตทุกตัวและจัดการกับแรงโน้มถ่วง

ทุกเฟรม SSSPWorld อัปเดตทุกส่วนของร่างกาย

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

เมื่อร่างกายชนกับวัตถุอื่นมันจะส่งผ่านความเร็วไปยังอีกความเร็วหนึ่งโดยการตั้งค่าความเร็วของร่างกายเป็นของมันเอง

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

นอกจากนี้เนื้อความจะเรียกเหตุการณ์ "ทับซ้อน" เมื่อมุม AABB ทั้งหมดซ้อนทับบางสิ่งบางอย่างในกรอบ

นี้คือรหัสที่มาแบบเต็มของเกมของฉัน มันแบ่งออกเป็นสามโครงการ SFMLStart เป็นอินพุตการจัดการไลบรารีภาพวาดและการอัพเดตเอนทิตีที่ง่าย SFMLStartPhysics เป็นสิ่งที่สำคัญที่สุดโดยที่คลาส SSSPBody และ SSSPWorld นั้น PlatformerPhysicsTest เป็นโครงการเกมที่มีตรรกะของเกมทั้งหมด

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


. gif แสดงสองปัญหา

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

ปัญหาแรก: ลำดับของการอัพเดท

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

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

เอ็นจิ้นฟิสิกส์ที่สำคัญ (Box2D, Bullet, Chipmunk) ทำหน้าที่จัดการลำดับการอัปเดตอย่างไร


ปัญหาที่สอง: มีเพียงหนึ่งลังเท่านั้นที่ถูกส่งไปยังเพดาน

ฉันยังไม่เข้าใจว่าทำไมสิ่งนี้เกิดขึ้น สิ่งที่ "สปริง" ทำคือตั้งค่าความเร็วของร่างกายเป็น -4000 และจัดตำแหน่งใหม่บนสปริงเอง แม้ว่าฉันจะปิดการใช้งานรหัสตำแหน่งใหม่ปัญหายังคงเกิดขึ้น

ความคิดของฉันคือเมื่อลังด้านล่างชนกับลังด้านบนความเร็วจะถูกตั้งค่าเป็น 0 ฉันไม่แน่ใจว่าทำไมสิ่งนี้ถึงเกิดขึ้น


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

ฉันไม่คิดว่าฉันจะหาทางแก้ปัญหาได้ด้วยตัวเองโดยไม่แยกคุณสมบัติมากมายออกจากเกม (เช่นการถ่ายโอนความเร็วและสปริงเป็นต้น)

ขอบคุณมากสำหรับเวลาที่ใช้ในการอ่านคำถามนี้และขอบคุณมากยิ่งขึ้นถ้าคุณลองหาวิธีแก้ปัญหาหรือข้อเสนอแนะ


เมื่อใดก็ตามที่คุณสแต็กกล่องคุณสามารถรวมฟิสิกส์ของพวกเขาเพื่อให้พวกเขาถือเป็นวัตถุเดียวได้หรือไม่
CiscoIPPhone

คำตอบ:


12

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

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

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

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

คุณสามารถสร้างเอฟเฟกต์แรงเสียดทานได้โดยการเบรกวัตถุในทิศทางตั้งฉากของการชนปริมาณการเบรกควรเทียบเท่ากับปริมาณการทับซ้อน

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

โค้ดหลอกบางอย่างในกรณีข้างต้นไม่ชัดเจนพอ:

//Presuming that you have done collision checks between two objects and now have  
//numbers for how much they overlap in each direction.
overlapX
overlapY
if(overlapX<overlapY){ //Do collision in direction X
    if(obj1.X>obj2.X){
        swap(obj1,obj2)
    }
    //Spring effect:
    obj1.addXvelocity-=overlapX*0.1 //Constant, the lower this is set the softer the  
                                    //collision will be.
    obj2.addXvelocity+=overlapX*0.1
    //Dampener effect:
    velocityDifference=obj2.Xvelocity-obj1.Xvelocity
    //velocityDifference=min(velocityDifference,0) //Uncomment to only dampen when  
                                                   //objects move towards each other.
    obj1.addXvelocity+=velocityDifference*0.1 //Constant, higher for more dampening.
    obj2.addXvelocity-=velocityDifference*0.1
    //Friction effect:
    if(obj1.Yvelocity>obj2.Yvelocity){
        swap(obj1,obj2)
    }
    friction=overlapX*0.01
    if(2*friction>obj2.Yvelocity-obj1.Yvelocity){
        obj1.addYvelocity+=(obj2.Yvelocity-obj1.Yvelocity)/2
        obj2.addYvelocity-=(obj2.Yvelocity-obj1.Yvelocity)/2
    }
    else{
        obj1.addYvelocity+=friction
        obj2.addYvelocity-=friction
    }
}
else{ //Do collision in direction Y

}

จุดของคุณสมบัติ addXvelocity และ addYvelocity คือสิ่งเหล่านี้จะถูกเพิ่มเข้าไปในความเร็วของวัตถุหลังจากการจัดการการชนทั้งหมดเสร็จสิ้น

แก้ไข:
คุณสามารถทำสิ่งต่าง ๆ ตามลำดับต่อไปนี้ซึ่งแต่ละ bullet จะต้องดำเนินการกับองค์ประกอบทั้งหมดก่อนที่จะดำเนินการต่อไป:

  • ตรวจจับการชนพวกเขาอาจได้รับการแก้ไขทันทีที่ตรวจพบ
  • เพิ่มค่า addVelocity ให้กับค่าความเร็วเพิ่มแรงโน้มถ่วง Yvelocity รีเซ็ตค่า addVelocity เป็น 0 ย้ายวัตถุตามความเร็วของพวกเขา
  • แสดงภาพ

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

แก้ไข 2:
การไหลของเครื่องยนต์ฟิสิกส์พื้นฐานมาก:

  • การชนและแรงโน้มถ่วงทำให้เกิดแรง / ความเร่ง acceleration = [Complicated formulas]
  • แรง / ความเร่งถูกเพิ่มเข้ากับความเร็ว velocity += acceleration
  • เพิ่มความเร็วในตำแหน่ง position += velocity

ดูดีไม่เคยคิดเกี่ยวกับมวลสปริงสำหรับ platformers ยกนิ้วให้สิ่งที่ enlightening :)
EnoughTea

ฉันจะลองใช้สิ่งนี้ในอีกไม่กี่ชั่วโมงเมื่อฉันกลับถึงบ้าน ฉันควรเคลื่อนที่ (ตำแหน่ง + = Velocity) พร้อมกันหรือไม่จากนั้นตรวจสอบการชนหรือย้ายและตรวจสอบการชนกันทีละตัว? [นอกจากนี้ฉันต้องแก้ไขตำแหน่งด้วยตนเองเพื่อแก้ไขการชนกันหรือไม่? หรือจะเปลี่ยนความเร็วในการจัดการกับสิ่งนั้น?]
Vittorio Romeo

ฉันไม่แน่ใจว่าจะตีความคำถามแรกของคุณได้อย่างไร ความละเอียดของการชนจะเปลี่ยนความเร็วและส่งผลต่อตำแหน่งทางอ้อมเท่านั้น
aaaaaaaaaaaa

ความจริงก็คือฉันย้ายเอนทิตีโดยการตั้งค่าความเร็วด้วยตนเองเป็นค่าที่แน่นอน ในการแก้ปัญหาการทับซ้อนฉันจะลบระยะห่างจากการทับซ้อนออกจากตำแหน่ง หากฉันใช้วิธีการของคุณฉันจะต้องย้ายเอนทิตีโดยใช้กำลังหรืออย่างอื่นหรือไม่ ฉันไม่เคยทำแบบนั้นมาก่อน
Vittorio Romeo

ในทางเทคนิคแล้วคุณต้องใช้กำลังในรหัสของฉันมันง่ายขึ้นเล็กน้อยเมื่อวัตถุทั้งหมดที่มีน้ำหนัก 1 และกำลังจึงเท่ากับการเร่งความเร็ว
aaaaaaaaaaaa

14

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

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

ปัญหาแรก

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

ในการดำเนินการโต้ตอบที่ซับซ้อนโดยไม่มีแฮ็คคุณจำเป็นต้องเพิ่มขั้นตอนเพิ่มเติมระหว่างการตรวจจับการชนตามตำแหน่งที่มีการเปลี่ยนแปลงโดยความเร็วเริ่มต้นและการเปลี่ยนแปลงตำแหน่งสุดท้ายตาม "after-velocity" ฉันคิดว่ามันจะเป็นเช่นนี้:

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

สิ่งเพิ่มเติมอาจปรากฏขึ้นเช่นการจัดการกับ jerking ปฏิเสธที่จะซ้อนกันเมื่อ FPS มีขนาดเล็กหรือสิ่งอื่น ๆ เช่นนั้นต้องเตรียม :)

ปัญหาที่สอง

ความเร็วแนวตั้งของทั้งสอง "ลังหนัก" กล่องไม่เคยเปลี่ยนแปลงจากศูนย์ ในวงอัปเดตของ PhysSpring คุณได้กำหนดความเร็ว แต่ในลูปอัปเดตของ PhysCrate จะมีค่าเป็นศูนย์อยู่แล้ว เป็นไปได้ที่จะหาบรรทัดที่ความเร็วผิดพลาด แต่ฉันหยุดการดีบั๊กที่นี่เนื่องจากเป็นสถานการณ์ "Reap What You Sew" ถึงเวลาที่จะหยุดการเข้ารหัสและเริ่มคิดใหม่ทุกอย่างเมื่อการดีบักกลายเป็นเรื่องยาก แต่ถ้ามันมาถึงจุดที่เป็นไปไม่ได้แม้แต่ผู้เขียนรหัสจะเข้าใจสิ่งที่เกิดขึ้นในรหัสแล้วฐานรหัสของคุณก็ตายไปแล้วโดยที่คุณไม่รู้ตัว :)

ปัญหาที่สาม

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


ฉันชอบการเปรียบเทียบ "ป่าสาหร่ายทะเล"
ชัด

จริง ๆ แล้วฉันรู้สึกละอายใจกับการใช้คำเหล่านี้ แต่ฉันรู้สึกว่ามันส่งผลในการ refactoring หรือสองหรือไม่ก็จะเป็นธรรม
EnoughTea

ด้วยการทดสอบเพียงครั้งเดียวที่tจะไม่มีความเป็นไปได้ที่จะเกิดสิ่งนี้หรือไม่? ฉันคิดว่าคุณจะต้องรวมความเร็วที่tแล้วตรวจสอบการชนในt + 1ก่อนกำหนดความเร็วใด ๆ เป็น 0
Jonathan Connell

ใช่เราตรวจจับการชนกันข้างหน้าหลังจากรวมสถานะเริ่มต้นล่วงหน้าจาก t ถึง t + dt โดยใช้ Runge-Kutta หรือบางสิ่ง
EnoughTea

"บูรณาการความเร็วโดยใช้กองกำลังทั้งหมดที่ทำหน้าที่ในร่างกาย" "ออกจากการคำนวณความเร็วกับเครื่องมือฟิสิกส์ของคุณ" - ฉันเข้าใจสิ่งที่คุณพยายามจะพูด แต่ฉันไม่มีเงื่อนงำเกี่ยวกับวิธีการทำเช่นนี้ มีตัวอย่าง / บทความใดบ้างที่คุณสามารถแสดงให้ฉันเห็น?
Vittorio Romeo

7

เมื่อร่างกายชนกับวัตถุอื่นมันจะส่งผ่านความเร็วไปยังอีกความเร็วหนึ่งโดยการตั้งค่าความเร็วของร่างกายเป็นของมันเอง

ปัญหาของคุณคือสิ่งเหล่านี้เป็นข้อสมมติฐานที่ผิดเกี่ยวกับการเคลื่อนไหวดังนั้นสิ่งที่คุณได้รับจะไม่คล้ายกับการเคลื่อนไหวตามที่คุณคุ้นเคย

เมื่อร่างกายชนกับอีกแรงจะได้รับการอนุรักษ์ การคิดถึงสิ่งนี้ในฐานะ "A hits B" กับ "B hits A" คือการใช้คำกริยาสกรรมกริยากับสถานการณ์ทางอกรรมกริยา A และ B ชนกัน; โมเมนตัมที่เกิดขึ้นจะต้องเท่ากับโมเมนตัมเริ่มต้น นั่นคือถ้า A และ B มีมวลเท่ากันตอนนี้พวกเขาทั้งคู่เดินทางด้วยความเร็วเฉลี่ยของพวกเขา

นอกจากนี้คุณยังอาจจำเป็นต้องมีการชนกันของข้อมูลและตัวแก้ซ้ำ ๆ หรือคุณจะพบปัญหาความมั่นคง คุณควรอ่านการนำเสนอ GDC ของ Erin Catto บางส่วน


2
พวกเขาจะได้รับค่าเฉลี่ยของความเร็วดั้งเดิมหากการปะทะกันไม่ยืดหยุ่นอย่างสมบูรณ์เช่น A และ B เป็นชิ้นส่วนของแป้ง
Mikael Öhman

"เพียงแค่ตั้งค่าความเร็วของร่างกายให้เป็นของตัวเอง" มันเป็นคำพูดแบบนี้ที่ให้ความสว่างว่าทำไมมันไม่ทำงาน โดยทั่วไปฉันมักพบว่าคนที่ไม่มีประสบการณ์เขียนระบบฟิสิกส์โดยไม่เข้าใจหลักการพื้นฐานที่เกี่ยวข้อง คุณไม่เคย 'ตั้งค่าความเร็ว' หรือ 'เพียงแค่ ... ' การปรับเปลี่ยนคุณสมบัติของร่างกายทุกครั้งควรใช้กฎของพลวัตโดยตรง รวมถึงการอนุรักษ์โมเมนตัมพลังงานและอื่น ๆ ใช่จะมีปัจจัยเหลวไหลเพื่อชดเชยความไร้เสถียรภาพ แต่คุณไม่สามารถเปลี่ยนความเร็วของร่างกายได้อย่างน่าอัศจรรย์
MrCranky

มันง่ายที่สุดที่จะสันนิษฐานว่าร่างกายไม่ยืดหยุ่นเมื่อพยายามให้เครื่องยนต์ทำงานในตอนแรกยิ่งซับซ้อนน้อยลงสำหรับการแก้ปัญหา
Patrick Hughes

4

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

  1. ช่วงกว้าง : วนรอบวัตถุทั้งหมด - ทำการทดสอบอย่างรวดเร็ว (เช่น AABB) เพื่อตรวจสอบว่าวัตถุใดที่อาจชนกัน - ทิ้งวัตถุที่ไม่ใช่
  2. เฟส Narrow : วนซ้ำวัตถุที่ชนกันทั้งหมด - คำนวณเวกเตอร์การเจาะสำหรับการชน (เช่นการใช้ SAT)
  3. การตอบสนองการชนกัน : วนรอบรายการการชนกันของเวกเตอร์ - คำนวณเวกเตอร์แรงตามมวลจากนั้นใช้ฟังก์ชันนี้เพื่อคำนวณเวกเตอร์การเร่งความเร็ว
  4. บูรณาการ : วนรอบเวกเตอร์ความเร่งทั้งหมดและรวมตำแหน่ง (และการหมุนหากจำเป็น)
  5. การแสดงผล : วนซ้ำตำแหน่งที่คำนวณทั้งหมดและแสดงผลแต่ละวัตถุ

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

ที่กล่าวว่าแต่ละส่วนเหล่านี้เป็นวิทยาศาสตร์ในตัวเองและสามารถใช้เวลามากพยายามที่จะหาทางออกที่ดีที่สุด อาจเป็นการดีกว่าถ้าคุณเริ่มต้นด้วยอัลกอริธึมที่ใช้บ่อยที่สุด:

  • การตรวจจับการชนกันของระยะกว้าง : คร่ำเครียดเชิงพื้นที่
  • การตรวจจับการชนกันของเฟสแคบ : สำหรับฟิสิกส์แบบเรียงต่อกันอย่างง่ายคุณสามารถใช้การทดสอบการตัดกันของกล่องแนวแกนตั้งศูนย์ (AABB) สำหรับรูปร่างซับซ้อนมากกว่าที่คุณสามารถใช้แยกแกนทฤษฎีบท ไม่ว่าคุณจะใช้อัลกอริธึมใดมันควรกลับทิศทางและความลึกของจุดตัดระหว่างวัตถุสองชิ้น (เรียกว่าการสอดใส่เวกเตอร์)
  • การตอบสนองการชนกัน : ใช้การฉายเพื่อแก้ไขการแทรกซึม
  • บูรณาการ : ผู้รวบรวมเป็นตัวกำหนดที่ใหญ่ที่สุดของความเสถียรและความเร็วของเครื่องยนต์ ตัวเลือกยอดนิยมสองตัวเลือกคือVerlet (รวดเร็ว แต่ง่าย) หรือการรวม RK4 (แม่นยำ แต่ช้า) การใช้การบูรณาการ verlet สามารถนำไปสู่การออกแบบที่เรียบง่ายเป็นอย่างมากเนื่องจากพฤติกรรมทางกายภาพส่วนใหญ่ (เด้ง, การหมุน) เพียงแค่ทำงานโดยไม่ต้องใช้ความพยายามมากเกินไป หนึ่งในแหล่งอ้างอิงที่ดีที่สุดที่ฉันได้เห็นสำหรับการเรียนรู้การรวม RK4 คือซีรีส์เกลนเลอร์ในฟิสิกส์สำหรับเกม

ที่ดี (และที่เห็นได้ชัด) สถานที่ที่จะเริ่มต้นอยู่กับกฎการเคลื่อนที่ของนิวตัน


ขอบคุณสำหรับการตอบกลับ. ฉันจะถ่ายโอนความเร็วระหว่างวัตถุได้อย่างไร เกิดขึ้นในช่วงการรวมระบบหรือไม่
Vittorio Romeo

ในความรู้สึกใช่ การถ่ายโอนความเร็วเริ่มต้นด้วยขั้นตอนการตอบสนองการชน นั่นคือเมื่อคุณคำนวณแรงที่กระทำต่อร่างกาย แรงแปลหมายถึงความเร่งโดยใช้สูตรการเร่ง = แรง / มวล การเร่งความเร็วจะใช้ในขั้นตอนการรวมเพื่อคำนวณความเร็วซึ่งจะใช้ในการคำนวณตำแหน่ง ความแม่นยำของขั้นตอนการรวมจะเป็นตัวกำหนดว่าการเปลี่ยนแปลงความเร็ว (และตำแหน่งในภายหลัง) จะมีความแม่นยำได้อย่างไร
ลุคแวนใน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.