ฉันจะทำการจำลองทางฟิสิกส์ที่กำหนดขึ้นได้อย่างไร


43

ฉันกำลังสร้างเกมฟิสิกส์ที่เกี่ยวข้องกับวัตถุแข็งเกร็งซึ่งผู้เล่นเคลื่อนย้ายชิ้นส่วนและชิ้นส่วนเพื่อไขปริศนา / แผนที่ สิ่งสำคัญอย่างยิ่งของเกมคือเมื่อผู้เล่นเริ่มทำการจำลองสถานการณ์มันจะทำงานแบบเดียวกันทุกที่โดยไม่คำนึงถึงระบบปฏิบัติการตัวประมวลผลและอื่น ๆ ...

มีห้องสำหรับความซับซ้อนจำนวนมากและการจำลองอาจทำงานเป็นเวลานานดังนั้นจึงเป็นเรื่องสำคัญที่เอนจิ้นฟิสิกส์จะกำหนดอย่างสมบูรณ์เกี่ยวกับการทำงานของจุดลอยตัวมิฉะนั้นวิธีแก้ปัญหาอาจปรากฏขึ้นเพื่อ "แก้ปัญหา" บนเครื่องของผู้เล่นคนหนึ่งและ "ล้มเหลว" กับอีกรายการหนึ่ง

ฉันจะบรรลุระดับนี้ในเกมของฉันได้อย่างไร ฉันยินดีที่จะใช้กรอบและภาษาที่หลากหลายรวมถึง Javascript, C ++, Java, Python และ C #

ฉันถูกล่อลวงโดย Box2D (C ++) เช่นเดียวกับภาษาอื่นที่เทียบเท่าเนื่องจากดูเหมือนว่าจะตอบสนองความต้องการของฉัน แต่มันขาดการกำหนดจุดลอยตัวโดยเฉพาะอย่างยิ่งกับฟังก์ชันตรีโกณมิติ

ตัวเลือกที่ดีที่สุดที่ฉันเคยเห็นมาแล้วนั้นเทียบเท่ากับ Java ของ Box2D (JBox2D) ดูเหมือนจะใช้ความพยายามในการกำหนดระดับจุดลอยตัวโดยใช้StrictMathมากกว่าMathสำหรับการใช้งานหลายอย่าง แต่ก็ไม่มีความชัดเจนว่าเอ็นจิ้นนี้จะรับประกันทุกสิ่งที่ฉันต้องการเพราะฉันยังไม่ได้สร้างเกม

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

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

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

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


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

คำตอบ:


45

ในการจัดการตัวเลขทศนิยมในลักษณะที่กำหนด

จุดลอยตัวเป็นตัวกำหนด ก็ควรจะเป็น มันซับซ้อน.

มีวรรณกรรมมากมายเกี่ยวกับตัวเลขจุดลอยตัว:

และพวกเขามีปัญหาอย่างไร:

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


อินพุตหนึ่งที่ทำให้เกิดปัญหาคือเวลา

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

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

ดังนั้น:

  • วัดเวลา: ใช่
  • ใช้เวลาในการจำลอง: ไม่

ตอนนี้สั่งการเรียนการสอนใหม่

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

และไม่การใช้ double จะไม่ช่วยคุณ

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

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

ดังนั้น:

  • เอิร์น ... อืม ... ใช้คอมไพเลอร์ที่ช่วยให้คุณกำหนดค่าวิธีที่พวกเขาจัดการกับจำนวนจุดลอย ยกตัวอย่างเช่นเห็น/ FP (ระบุพฤติกรรมจุดลอยตัว)

กรณีสำหรับหมายเลขจุดคงที่

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

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

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

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

ดังนั้น:

  • เก็บค่าเล็ก: ใช่
  • การปัดเศษอย่างระมัดระวัง: ใช่
  • กำหนดหมายเลขจุดคงที่เมื่อทำได้: ใช่

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

คุณรู้หรือไม่ว่าพวกเขาทำสิ่งเช่นนั้นสำหรับ PlayStation ดั้งเดิม? กรุณาพบสุนัขของฉัน, แพทช์

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

ดังนั้น: ใช้จุดคงที่ตัวเลข


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

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


ดูสิ่งนี้ด้วย:


ภาคผนวก : ฉันแนะนำให้รักษาขนาดของโลกให้เล็ก ด้วยที่กล่าวว่าทั้ง OP และ Jibb Smart นำมาซึ่งจุดที่เคลื่อนที่ห่างจากจุดกำเนิดดั้งเดิมนั้นมีความแม่นยำน้อยกว่า นั่นจะมีผลต่อฟิสิกส์หนึ่งอันที่จะเห็นได้เร็วกว่าขอบโลก หมายเลขจุดคงที่ดีมีความแม่นยำคงที่พวกเขาจะดีเท่า ๆ กัน (หรือไม่ดีถ้าคุณต้องการ) ทุกที่ ซึ่งจะดีถ้าเราต้องการระดับ ฉันยังต้องการพูดถึงว่าวิธีที่เราทำฟิสิกส์มักจะมีคุณสมบัติในการขยายรูปแบบขนาดเล็ก ดูผีเสื้อผล - ตายตัวฟิสิกส์ใน The Incredible เครื่องจักรและ contraption ชง


อีกวิธีในการทำฟิสิกส์

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

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

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


อย่างไรก็ตามยังมีข้อโต้แย้งว่าไม่ได้ทำงานในที่ที่สะสมข้อผิดพลาดมากมาย บางทีนี่อาจเป็นโอกาสในการทำฟิสิกส์ในวิธีที่ต่างออกไป

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

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

ใช่นั่นเป็นงานจำนวนมากของขั้นตอนการจำลองเดียว นั่นหมายความว่าการจำลองจะไม่เริ่มต้นทันที ...

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

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


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


หมายเหตุ : หากเรากำลังทำตัวเลขทศนิยมนี้วิธีการนี้จะไม่แก้ปัญหาของวัตถุที่มีพฤติกรรมแตกต่างไปจากแหล่งกำเนิด อย่างไรก็ตามในขณะที่มันเป็นความจริงที่ความแม่นยำหายไปไกลกว่าที่คุณไปจากแหล่งกำเนิดที่ยังคงกำหนด ในความเป็นจริงนั่นคือเหตุผลที่ไม่ได้นำมาซึ่งเดิม


ภาคผนวก

จาก OP ในความคิดเห็น :

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

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


ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
Vaillancourt

2
คำตอบที่ดี! 2 จุดเพิ่มเติมสำหรับจุดคงที่: 1. จุดลอยตัวจะทำงานใกล้หรือไกลจากจุดกำเนิดมากขึ้น (ถ้าคุณมีตัวต่อที่เหมือนกันในที่อื่น) แต่จุดคงที่จะไม่ 2. จุดคงที่จริงมีมากขึ้นมีความแม่นยำกว่าจุดลอยมากที่สุดในช่วงของ - คุณสามารถได้รับความแม่นยำโดยใช้จุดคงดี
Jibb สมาร์ท

เป็นไปได้ที่จะเข้ารหัสข้อมูลไบนารีทั้งใน XML และ JSON โดยใช้base64องค์ประกอบ ไม่ใช่วิธีที่มีประสิทธิภาพในการแสดงข้อมูลจำนวนมาก แต่ไม่ถูกต้องที่จะบอกเป็นนัยว่าพวกเขาป้องกันการใช้การเป็นตัวแทนไบนารี
Pikalek

1
@Pikalek ฉันรู้ว่า OP ถามฉันเกี่ยวกับความคิดเห็นที่ฉันพูดถึง base64 เป็นตัวเลือกหนึ่งในหมู่อื่น ๆ รวมถึง hex, reinterpret cast เป็น int และใช้รูปแบบ protobuf เพราะไม่มีใครจะเข้าใจไฟล์เหล่านั้นพวกเขาไม่ได้ (ไม่ได้รับการฝึกฝน ) มนุษย์อ่านได้ จากนั้น - ฉันถือว่า - mod ลบความคิดเห็น (ไม่มันไม่ได้อยู่ในการแชทที่ลิงค์ด้านบน) จะเกิดอะไรขึ้นอีกครั้ง? ฉันควรลบสิ่งนั้นออกจากคำตอบหรือไม่ ฉันควรทำให้มันนานขึ้นหรือไม่
ธีระโรจน์

@Theraot Ah ฉันเห็นว่าฉันอาจตีความว่าแตกต่างกันในบริบทของตั้งแต่ลบความคิดเห็น (FWIW ฉันอ่านการสนทนาทั้งคำตอบและคำถาม) และแม้ว่าจะมีวิธีการเข้ารหัสข้อมูลดั้งเดิมที่มีประสิทธิภาพ แต่ก็ยังมีเรื่องที่ใหญ่กว่าในการตรวจสอบให้แน่ใจว่ามันหมายถึงสิ่งเดียวกันทั่วทั้งแพลตฟอร์ม รับปั่นอาจจะดีที่สุดที่จะเพียงแค่ปล่อยให้มันเป็น ขอบคุณสำหรับการชี้แจง!
Pikalek

6

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

การใช้คอมไพเลอร์ที่แตกต่างกันหรือคอมไพเลอร์เดียวกันกับการตั้งค่าที่แตกต่างกันหรือแม้กระทั่งเวอร์ชั่นที่แตกต่างกันของคอมไพเลอร์เดียวกันสามารถทำลายการกำหนด

หากคุณต้องการ crossplay ระหว่างแพลตฟอร์มหรือเวอร์ชั่นเกมฉันคิดว่าคุณจะต้องไปจุดคงที่ - crossplay ที่เป็นไปได้เพียงอย่างเดียวซึ่งฉันทราบด้วย floating point อยู่ระหว่าง PC และ XBox1 แต่มันค่อนข้างบ้า

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

หากคุณกำลังพยายามที่จะม้วนสิ่งของของคุณเองบางสิ่งที่สามารถช่วย:

  • การลอย IEE754 นั้นถูกกำหนดไว้หากคุณไม่ได้ทำอะไรเลยที่มีผลไม้มากเกินไป (google "IEE754 ดีกรี" สำหรับข้อมูลเพิ่มเติมเกี่ยวกับสิ่งที่เป็นหรือไม่ได้กล่าวถึง)
  • คุณต้องแน่ใจว่าไคลเอนต์ทุกคนมีโหมดการปัดเศษและตั้งค่าความแม่นยำเหมือนกัน (ใช้ controlfp เพื่อตั้งค่า)
  • โหมดการปัดเศษและความแม่นยำสามารถเปลี่ยนแปลงได้โดยห้องสมุดคณิตศาสตร์บางแห่งดังนั้นหากคุณใช้ libs ที่ปิดอยู่คุณอาจต้องการตรวจสอบสิ่งเหล่านี้หลังจากทำการโทร (อีกครั้งโดยใช้ controlfp เพื่อตรวจสอบ)
  • คำสั่ง SIMD บางคำสั่งไม่แน่นอนระวังให้มาก
  • ดังที่ได้กล่าวไว้ข้างต้นเพื่อให้มั่นใจว่าคุณต้องมีแพลตฟอร์มเดียวกันรุ่นที่แน่นอนเดียวกันของคอมไพเลอร์เดียวกันรวบรวมการตั้งค่าเดียวกันด้วยการตั้งค่าคอมไพเลอร์เดียวกัน
  • สร้างเครื่องมือบางอย่างเพื่อตรวจหาสถานะ desyncs และช่วยวินิจฉัยพวกมัน - เช่น CRC สถานะของเกมทุกเฟรมที่ตรวจพบเมื่อ desync เกิดขึ้นจากนั้นมีโหมดการบันทึก verbose ที่คุณสามารถเปิดใช้งานเมื่อมีการปรับเปลี่ยนสถานะของเกม จากนั้นนำไฟล์ 2 ไฟล์จากแบบจำลองที่แยกจากกันและเปรียบเทียบในเครื่องมือ diff เพื่อดูว่ามันผิดพลาดที่ไหน
  • เริ่มต้นตัวแปรทั้งหมดของคุณในสถานะเกมแหล่งหลักของ desyncs
  • การจำลองเกมทั้งหมดจะต้องเกิดขึ้นในลำดับเดียวกันทุกครั้งเพื่อหลีกเลี่ยงการ desyncs มันง่ายอย่างไม่น่าเชื่อที่จะทำสิ่งนี้ผิดแนะนำให้ใช้โครงสร้างการจำลองเกมของคุณในลักษณะที่ลดสิ่งนี้ลง ฉันไม่ใช่คนที่มีรูปแบบการออกแบบซอฟต์แวร์ แต่สำหรับกรณีนี้มันอาจเป็นความคิดที่ดี - คุณอาจพิจารณารูปแบบบางอย่างที่การจำลองเกมเหมือนกล่องนิรภัยและวิธีเดียวที่จะกลายพันธุ์ของเกมคือการแทรก "messages" หรือ "command" โดยมีการเข้าถึง const เพียงอย่างเดียวที่มอบให้กับสิ่งใดก็ตามที่อยู่นอกสถานะเกม (เช่นการเรนเดอร์เครือข่าย ฯลฯ ) ดังนั้นการสร้างเครือข่ายการจำลองสำหรับเกมที่มีผู้เล่นหลายคนเป็นกรณีของการส่งคำสั่งเหล่านี้ผ่านเครือข่ายหรือการเล่นซ้ำการจำลองเดียวกันเป็นกรณีของการบันทึกสตรีมของคำสั่งในครั้งแรก

1
Unity กำลังทำงานไปสู่เป้าหมายของการกำหนดข้ามแพลตฟอร์มด้วยระบบ Unity Physics ใหม่ของพวกเขาสำหรับ Data-Oriented Technology Stack แต่เมื่อฉันเข้าใจแล้วมันยังอยู่ระหว่างการพัฒนาและยังไม่เสร็จสมบูรณ์ / พร้อมที่จะใช้งานจากชั้นวาง
DMGregory

ตัวอย่างของคำสั่ง SIMD ที่ไม่ได้กำหนดไว้คืออะไร? คุณกำลังคิดของคนโดยประมาณเป็นrsqrtpsอย่างไร
Ruslan

@DMGregory ต้องเป็นภาพตัวอย่างในขณะที่คุณสามารถใช้งานได้แล้ว - แต่อย่างที่คุณบอกว่ามันยังไม่เสร็จ
โจ

@ Ruslan ใช่ rsqrtps / rcpps ผลลัพธ์ขึ้นอยู่กับการติดตั้ง
Joe

5

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

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


1
ฉันเห็นด้วยอย่างยิ่ง นี่คือวิธีที่คุณรับประกันประสบการณ์การแชร์กับผู้ใช้ทั้งหมด gamedev.stackexchange.com/questions/6645/…เรียงลำดับของหัวข้อที่คล้ายกันเปรียบเทียบความแตกต่างระหว่างฝั่งไคลเอ็นต์กับฝั่งฟิสิกส์ฝั่งเซิร์ฟเวอร์
ทิมโฮลต์

1

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

ลดความแม่นยำ

ใช้ขนาดขั้นตอนเวลาคงที่ที่กำหนดไว้ล่วงหน้าดำเนินการทางฟิสิกส์ในแต่ละขั้นตอนในการลอยความแม่นยำสองเท่าแบบมาตรฐาน แต่จากนั้นทำการคำนวณความละเอียดของตัวแปรทั้งหมดให้มีความแม่นยำเดียว (หรือบางสิ่งที่แย่กว่านั้น) หลังจากแต่ละขั้นตอน จากนั้นความเบี่ยงเบนที่เป็นไปได้ส่วนใหญ่ที่การจัดลำดับใหม่แบบลอยตัวอาจแนะนำ (เมื่อเปรียบเทียบกับการรันการอ้างอิงของโปรแกรมเดียวกัน) จะถูกตัดออกเนื่องจากการเบี่ยงเบนเหล่านั้นเกิดขึ้นในหลักที่ไม่มีความแม่นยำลดลง ดังนั้นการเบี่ยงเบนจึงไม่ได้รับโอกาสจากการสะสมของ Lyapunov (Butterfly Effect) ที่จะกลายเป็นสิ่งที่น่าสังเกต

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

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


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


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

ใช่เป็นไปได้ที่ฉันได้กล่าวไปแล้วในคำตอบ แต่มันจะเกิดขึ้นน้อยมากเช่นเดียวกับข้อบกพร่องอื่น ๆ ในเกมฟิสิกส์ ดังนั้นการปัดเศษจึงช่วยได้ (ผมจะไม่ลงรอบแม้ว่า; รอบใกล้ที่สุดเพื่อหลีกเลี่ยงการให้น้ำหนัก.)
leftaroundabout

0

สร้างคลาสของคุณเองเพื่อเก็บหมายเลข!

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

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


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

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

0

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

นี่คือวิดีโอของอุปกรณ์จริงที่พฤติกรรมไม่สามารถคาดการณ์ได้โดยเจตนายกเว้นในแง่สถิติ:

https://www.youtube.com/watch?v=EvHiee7gs9Y

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

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

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

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

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

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


1
ฉันไม่เห็นความสับสนในคำศัพท์ OP ต้องการพฤติกรรมที่กำหนดจากระบบที่อาจเกิดความสับสน นั่นเป็นไปได้ทั้งหมด
ทำเครื่องหมาย

การใช้รูปร่างที่เรียบง่ายกว่า (เช่นวงกลมและสี่เหลี่ยม) จะไม่เปลี่ยนปัญหาเลย คุณยังต้องการฟังก์ชันตรีโกณมิติ, sqrt, และอื่น ๆ อีกมากมาย
jvn91173

-1

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

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


11
วิธีที่แม่นยำสองวิ่งปะทะกันของผลผีเสื้อ ในระบบพลวัต (เช่นซิมฟิสิกส์) แม้แต่ความเบี่ยงเบนเล็ก ๆ ในสภาวะเริ่มต้นสามารถขยายผ่านการป้อนกลับได้ทำให้เกิดข้อผิดพลาดที่สังเกตเห็นได้ ตัวเลขพิเศษทั้งหมดคือการหน่วงเวลานี้อีกเล็กน้อย - บังคับให้ก้อนหิมะกลิ้งไปอีกเล็กน้อยก่อนที่มันจะใหญ่พอที่จะทำให้เกิดปัญหา
DMGregory

2
ข้อผิดพลาดสองข้อในครั้งเดียว: 1) จุดลอยตัวคู่ประสบปัญหาเดียวกันและมักจะเลื่อนปัญหาไปสู่การแก้ไขข้อบกพร่องในอนาคต 2) ไม่มีกฎที่ระบุว่าจุดคงที่จะต้องแม่นยำน้อยกว่าจุดลอยตัว ขึ้นอยู่กับขนาดและปัญหาที่เกิดขึ้นหรือในหน่วยความจำที่คุณพร้อมที่จะใช้ต่อหมายเลขจุดคงที่พวกเขาสามารถแม่นยำน้อยกว่าแม่นยำเท่าเทียมกันหรือแม่นยำยิ่งขึ้น ไม่สมเหตุสมผลที่จะพูดว่า "แม่นยำน้อยลง"
phresnel

@phresnel เป็นตัวอย่างของความแม่นยำจุดคงที่, IBM 1400 series ใช้เลขทศนิยมทศนิยมแบบกำหนดแน่นอนโดยพลการ อุทิศตัวเลข 624 หลักให้กับแต่ละหมายเลขและคุณมีช่วงและความแม่นยำของจุดลอยตัวที่มีความแม่นยำสองเท่า
ทำเครื่องหมาย

@phresnel (2) จุดดี ฉันอัปเดตคำตอบเพื่อรับจำนวนบิตเท่ากัน
Evorlor

-2

ใช้รูปแบบของที่ระลึก

ในการรันครั้งแรกของคุณให้บันทึกข้อมูลตำแหน่งในแต่ละเฟรมหรือมาตรฐานใด ๆ ที่คุณต้องการ ถ้ามันไม่มีประสิทธิภาพเกินไปให้ทำทุก ๆ n เฟรม

จากนั้นเมื่อคุณสร้างการจำลองขึ้นมาให้ทำตามฟิสิกส์ตามอำเภอใจ แต่อัพเดทข้อมูลตำแหน่งทุก ๆ เฟรม n

รหัสหลอกง่ายเกินไป:

function Update():
    if(firstRun) then (SaveData(frame, position));
    else if(reproducedRun) then (this.position = GetData(frame));

9
ฉันไม่คิดว่ามันจะใช้ได้กับกรณีของ OP สมมติว่าคุณกับฉันกำลังเล่นเกมกับระบบที่ต่างกัน เราแต่ละคนวางชิ้นส่วนของจิ๊กซอว์ในลักษณะเดียวกัน - เป็นคำตอบที่ผู้พัฒนาไม่คาดการณ์ล่วงหน้า เมื่อคุณคลิก "เริ่ม" พีซีของคุณจำลองฟิสิกส์เพื่อให้การแก้ปัญหาสำเร็จ เมื่อฉันทำแบบเดียวกันความแตกต่างเล็กน้อยในการจำลองจะนำไปสู่โซลูชัน (เหมือนกัน) ของฉันซึ่งไม่ได้ให้คะแนนว่าประสบความสำเร็จ ที่นี่ฉันไม่มีโอกาสปรึกษาที่ระลึกจากความสำเร็จของคุณเพราะมันเกิดขึ้นในเครื่องของคุณไม่ใช่เวลา dev
DMGregory

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