เกมที่กำหนดขึ้นมามีความเป็นไปได้อย่างไรในการเผชิญกับการไม่กำหนดระดับทศนิยม


52

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

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

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

โปรดทราบว่าฉันสนใจ C # เป็นหลักซึ่งเท่าที่ฉันสามารถบอกได้มีปัญหาเหมือนกับ C ++ ในเรื่องนี้


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

@ jhocking แต่อาจเป็นคำตอบที่ดีที่สุด
Jonathan Connell

starcraft II infacti ทำข้อมูลให้ตรงกันทุก ๆ ครั้งเท่านั้นฉันดูการเล่นเกมเพลย์กับเพื่อน ๆ ของฉันคอมพิวเตอร์แต่ละเครื่องอยู่เคียงข้างกันและมีความแตกต่าง ฉันมีบางยูนิตที่มีแผนที่ขนาด 6/7 อยู่ห่างออกไปไกลบนหน้าจอของฉันสำหรับเขาเอง
GameDeveloper

คำตอบ:


15

จุดลอยตัวกำหนดได้หรือไม่?

ฉันได้อ่านปัญหานี้หลายครั้งเมื่อไม่กี่ปีก่อนเมื่อฉันต้องการเขียน RTS โดยใช้สถาปัตยกรรม lockstep แบบเดียวกับที่คุณทำ

ข้อสรุปของฉันเกี่ยวกับจุดลอยตัวของฮาร์ดแวร์คือ:

  • รหัสแอสเซมบลีที่เหมือนกันส่วนใหญ่น่าจะเป็นตัวกำหนดหากคุณระมัดระวังในการตั้งค่าสถานะจุดลอยตัวและคอมไพเลอร์
  • มีโครงการโอเพ่นซอร์ส RTS หนึ่งโครงการที่อ้างว่าพวกเขาได้คอมไพล์ C / C ++ ที่กำหนดไว้ได้ในคอมไพเลอร์ต่างๆโดยใช้ไลบรารีแรปเปอร์ ฉันไม่ได้ยืนยันการอ้างสิทธิ์นั้น (ถ้าฉันจำได้ถูกต้องมันเป็นเรื่องเกี่ยวกับSTREFLOPห้องสมุด)
  • . NET JIT ได้รับอนุญาตให้ใช้งานได้ค่อนข้างนาน โดยเฉพาะอย่างยิ่งมันได้รับอนุญาตให้ใช้ความแม่นยำสูงกว่าที่ต้องการ นอกจากนี้ยังใช้ชุดคำสั่งต่าง ๆ ใน x86 และ AMD64 (ฉันคิดว่า x86 ใช้ x87, AMD64 ใช้คำสั่ง SSE บางอย่างซึ่งพฤติกรรมแตกต่างกันสำหรับ denorms)
  • คำแนะนำที่ซับซ้อน (รวมถึงฟังก์ชันตรีโกณมิติเลขชี้กำลังลอการิทึม) เป็นปัญหาโดยเฉพาะอย่างยิ่ง

ฉันสรุปได้ว่ามันเป็นไปไม่ได้ที่จะใช้ชนิดจุดลอยตัวที่สร้างขึ้นใน. net แบบไม่แน่นอน

วิธีแก้ไขที่เป็นไปได้

ดังนั้นฉันต้องการวิธีแก้ปัญหา ฉันพิจารณาแล้ว:

  1. ใช้งานFixedPoint32ใน C # แม้ว่านี่จะไม่ยากเกินไป (ฉันมีการนำไปใช้งานแล้วเสร็จครึ่งหนึ่ง) ค่าที่น้อยมากทำให้ใช้งานได้น่ารำคาญ คุณต้องระวังตลอดเวลาดังนั้นคุณจึงไม่ล้นและไม่แม่นยำจนเกินไป ในที่สุดฉันพบว่ามันไม่ง่ายกว่าการใช้จำนวนเต็มโดยตรง
  2. ใช้งานFixedPoint64ใน C # ฉันพบว่ามันค่อนข้างยากที่จะทำ สำหรับการดำเนินการบางอย่างจำนวนเต็มระดับกลางของ 128 บิตจะเป็นประโยชน์ แต่. net ไม่ได้เสนอประเภทดังกล่าว
  3. ใช้รหัสเนทีฟสำหรับการดำเนินการทางคณิตศาสตร์ซึ่งกำหนดไว้ล่วงหน้าบนแพลตฟอร์มเดียว เกิดค่าใช้จ่ายในการโทรของผู้รับมอบสิทธิ์ในการดำเนินการทางคณิตศาสตร์ทุกครั้ง สูญเสียความสามารถในการเรียกใช้ข้ามแพลตฟอร์ม
  4. Decimalใช้ แต่มันช้าใช้หน่วยความจำจำนวนมากและสามารถโยนข้อยกเว้นได้ง่าย (หารด้วย 0 ล้น) มันดีมากสำหรับการใช้ทางการเงิน แต่ไม่เหมาะสำหรับเกม
  5. ใช้จุดลอยตัว 32 บิตแบบกำหนดเอง ฟังดูค่อนข้างยากในตอนแรก การไม่มี BitScanReverse ภายในทำให้เกิดความรำคาญเล็กน้อยเมื่อใช้งานสิ่งนี้

SoftFloat ของฉัน

ได้รับแรงบันดาลใจจากการโพสต์ของคุณบน StackOverflowฉันเพิ่งเริ่มใช้ชนิดจุดลอยตัว 32 บิตในซอฟต์แวร์และผลลัพธ์มีแนวโน้ม

  • การแสดงหน่วยความจำเป็นแบบไบนารีที่เข้ากันได้กับ IEEE ลอยดังนั้นฉันสามารถตีความหมายอีกครั้งเมื่อส่งออกไปยังรหัสกราฟิก
  • รองรับ SubNorms, infinities และ NaNs
  • ผลลัพธ์ที่แน่นอนไม่เหมือนกับผลลัพธ์ IEEE แต่โดยทั่วไปจะไม่สำคัญสำหรับเกม ในรหัสประเภทนี้มันเป็นเรื่องสำคัญที่ผลลัพธ์จะเหมือนกันสำหรับผู้ใช้ทุกคนไม่ใช่ว่ามันถูกต้องกับหลักสุดท้าย
  • ประสิทธิภาพถือว่าดี การทดสอบเล็กน้อยแสดงให้เห็นว่าสามารถทำได้ประมาณ 75MFLOPS เทียบกับ 220-260MFLOPS ด้วยfloatการเพิ่ม / การคูณ (เธรดเดี่ยวบน 2.66GHz i3) หากใครมีมาตรฐานจุดลอยตัวที่ดีสำหรับ. net โปรดส่งมาให้ฉันเนื่องจากการทดสอบปัจจุบันของฉันเป็นพื้นฐานมาก
  • สามารถปรับปรุงการปัดเศษ ขณะนี้มันตัดทอนซึ่งสอดคล้องกับการปัดเศษเป็นศูนย์
  • มันยังไม่สมบูรณ์มาก ปัจจุบันการแบ่งการปลดเปลื้องและการดำเนินการทางคณิตศาสตร์ที่ซับซ้อนหายไป

หากใครต้องการมีส่วนร่วมในการทดสอบหรือปรับปรุงรหัสเพียงติดต่อฉันหรือออกคำขอดึงใน GitHub https://github.com/CodesInChaos/SoftFloat

แหล่งอื่น ๆ ของความไม่แน่นอน

นอกจากนี้ยังมีแหล่งที่มาอื่น ๆ ของ indeterminism ใน. net

  • วนซ้ำDictionary<TKey,TValue>หรือHashSet<T>คืนองค์ประกอบในลำดับที่ไม่ได้กำหนด
  • object.GetHashCode() แตกต่างจากวิ่งไปวิ่ง
  • การใช้งานRandomคลาสในตัวไม่ได้ระบุใช้งานของคุณเอง
  • การมัลติเธรดพร้อมการล็อกที่ไร้เดียงสานำไปสู่การจัดเรียงใหม่และผลลัพธ์ที่ต่างกัน ระวังการใช้เธรดอย่างถูกต้อง
  • เมื่อWeakReferenceสูญเสียเป้าหมายจะไม่สามารถกำหนดได้เพราะ GC อาจทำงานได้ตลอดเวลา

23

คำตอบสำหรับคำถามนี้มาจากลิงค์ที่คุณโพสต์ คุณควรอ่านคำพูดจากเกม Gas Powered โดยเฉพาะ:

ฉันทำงานที่ Gas Powered Games และฉันสามารถบอกคุณได้โดยตรงว่าคณิตศาสตร์จุดลอยตัวนั้นถูกกำหนดไว้แล้ว คุณต้องมีชุดคำสั่งและคอมไพเลอร์ชุดเดียวกันและแน่นอนว่าตัวประมวลผลของผู้ใช้เป็นไปตามมาตรฐาน IEEE754 ซึ่งรวมถึงพีซีทั้งหมดของเราและลูกค้า 360 คน เครื่องยนต์ที่ใช้ DemiGod ผู้บัญชาการทหารสูงสุด 1 และ 2 นั้นใช้มาตรฐาน IEEE754 ไม่พูดถึงอาจเป็นเกม RTS peer to peer อื่น ๆ ในตลาด

และด้านล่างนั้นคือ:

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

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


2
ดังที่ฉันได้กล่าวไปแล้วฉันสนใจ C # เป็นหลัก; ตั้งแต่ JIT ทำการคอมไพล์จริงฉันไม่สามารถรับประกันได้ว่ามันเป็น"คอมไพล์ด้วยการตั้งค่าการเพิ่มประสิทธิภาพเดียวกัน"แม้ในขณะที่รันไฟล์ปฏิบัติการเดียวกันบนเครื่องเดียวกัน!
BlueRaja - Danny Pflughoeft

2
บางครั้งโหมดการปัดเศษถูกตั้งค่าแตกต่างกันใน fpu ในสถาปัตยกรรมบางรุ่น fpu มีการลงทะเบียนภายในที่มีขนาดใหญ่กว่าความแม่นยำสำหรับการคำนวณ ... ในขณะที่ IEEE754 ไม่ได้ให้ความสำคัญกับวิธีการทำงานของ FP ไม่เจาะจงว่าควรใช้ฟังก์ชั่นทางคณิตศาสตร์ใดโดยเฉพาะซึ่งอาจเปิดเผยความแตกต่างทางสถาปัตยกรรม
Stephen

4
@ 3nixios ด้วยการตั้งค่าแบบนั้นเกมดังกล่าวไม่สามารถกำหนดได้ เกมที่มีการประทับเวลาคงที่เท่านั้นที่สามารถกำหนดได้ คุณกำลังโต้เถียงบางสิ่งบางอย่างที่ไม่ได้กำหนดไว้แล้วเมื่อเรียกใช้การจำลองบนเครื่องเดียว
AttackHobo

4
@ 3nixios "ฉันระบุว่าแม้จะมีการประทับเวลาคงที่ไม่มีอะไรรับประกันว่าการประทับเวลาจะยังคงอยู่เสมอ" คุณผิดอย่างสิ้นเชิง จุดของการประทับเวลาที่แน่นอนคือการมีเวลาเดลต้าที่เหมือนกันสำหรับแต่ละเครื่องหมายในการอัปเดต
AttackHobo

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

3

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


ใช่ฉันสามารถทำให้มันเป็นไคลเอนต์ - เซิร์ฟเวอร์และจัดการกับอาการปวดหัวของการทำนายและการคาดการณ์ฝั่งไคลเอ็นต์ คำถามนี้เกี่ยวกับสถาปัตยกรรมเพียร์ทูเพียร์ซึ่งน่าจะง่ายกว่า ...
BlueRaja - Danny Pflughoeft

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

เซิร์ฟเวอร์ / ไคลเอนต์เป็นวิธีเดียวในการสร้างเกมบนเครือข่าย อีกวิธีที่นิยม (โดยเฉพาะอย่างยิ่งสำหรับเช่น. เกม RTS เช่น C & C หรือตาร์คราฟ) เป็นแบบ peer-to-peer ซึ่งมีคือไม่มีเซิร์ฟเวอร์ที่มีสิทธิ์ เพื่อให้เป็นไปได้การคำนวณทั้งหมดจะต้องถูกกำหนดอย่างสมบูรณ์และสอดคล้องกับลูกค้าทั้งหมด - ดังนั้นคำถามของฉัน
BlueRaja - Danny Pflughoeft

ไม่ใช่ว่าคุณจะต้องทำให้เกมเป็น p2p อย่างเคร่งครัดโดยไม่มีเซิร์ฟเวอร์ / ไคลเอนต์ที่ยกระดับ ถ้าคุณจำเป็นต้องใช้ - ให้ใช้ fixed-point
ไม่เป็นไร

3

แก้ไข: ลิงก์ไปยังระดับจุดคงที่ (ผู้ซื้อระวัง! - ฉันไม่ได้ใช้ ... )

คุณสามารถถอยกลับไปใช้เลขคณิตของจุดคงที่ได้เสมอ มีคน (ทำ rts ไม่น้อยกว่า) ได้ทำเลกทำงานกับstackoverflowเรียบร้อยแล้ว

คุณจะจ่ายค่าปรับตามผลงาน แต่สิ่งนี้อาจจะใช่หรือไม่ใช่ปัญหาก็ได้เนื่องจาก. net จะไม่เป็นนักแสดงที่นี่โดยเฉพาะเพราะมันจะไม่ใช้คำสั่ง simd เกณฑ์มาตรฐาน!

NB ดูเหมือนว่าบางคนที่intelดูเหมือนจะมีทางออกให้คุณใช้ไลบรารี่ของ primitive performance ของ c # สิ่งนี้อาจช่วยให้ vectorising รหัสจุดคงที่เพื่อชดเชยประสิทธิภาพที่ช้าลง


decimalจะทำงานได้ดีสำหรับที่เกินไป; แต่สิ่งนี้ยังคงมีปัญหาเช่นเดียวกับการใช้intฉันจะทำตรีโกณมิติกับมันได้อย่างไร
BlueRaja - Danny Pflughoeft

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

อีกวิธีหนึ่งคุณอาจสามารถแทนที่การโทรด้วยตรีโกณมิติด้วยตัวเลขในจินตนาการหรือ quaternions (ถ้าเป็น 3D) นี่เป็นคำอธิบายที่ยอดเยี่ยม
ลุ

สิ่งนี้อาจช่วยได้
ลุ

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

3

ฉันเคยทำงานกับหนังสือจำนวนมากมาแล้ว

คำตอบสั้น ๆ : เป็นไปได้ถ้าคุณเข้มงวดมาก แต่อาจไม่คุ้มค่า ถ้าคุณไม่ได้อยู่กับสถาปัตยกรรมแบบตายตัว (read: console) มันจะพิถีพิถันเปราะบางและมีปัญหารองมากมายเช่นการเข้าร่วมช้า

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

ความแตกต่างของแพลตฟอร์มเหล่านี้อยู่ในซิลิคอนไม่ใช่ซอฟต์แวร์ดังนั้นเพื่อตอบคำถามของคุณ C # ก็จะได้รับผลกระทบเช่นกัน คำแนะนำเช่น fused multiply-add (FMA) vs ADD + MUL เปลี่ยนผลลัพธ์เพราะมันปัดเศษภายในเพียงครั้งเดียวแทนที่จะเป็นสองครั้ง C ช่วยให้คุณควบคุมได้มากขึ้นเพื่อบังคับให้ CPU ทำสิ่งที่คุณต้องการโดยทั่วไปโดยไม่รวมการดำเนินการเช่น FMA เพื่อสร้างสิ่งที่ "มาตรฐาน" - แต่ด้วยความเร็ว อินทรินดูเหมือนว่าจะแตกต่างกันมากที่สุด ในโครงการหนึ่งฉันต้องขุดหนังสือ acos table อายุ 150 ปีเพื่อให้ได้ค่าสำหรับการเปรียบเทียบเพื่อกำหนด CPU ที่ "ถูกต้อง" ซีพียูจำนวนมากใช้การประมาณพหุนามสำหรับฟังก์ชันตรีโกณมิติ แต่ไม่ได้มีสัมประสิทธิ์เดียวกันเสมอไป

คำแนะนำของฉัน:

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

มีบทความดีๆเกี่ยวกับ Source engine ที่อธิบายวิธีหนึ่งในการซิงค์: https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking

โปรดจำไว้ว่าหากคุณสนใจที่จะเข้าร่วมช้าคุณจะต้องกัดกระสุนและทำให้ข้อมูลตรงกัน


1

โปรดทราบว่าฉันสนใจ C # เป็นหลักซึ่งเท่าที่ฉันสามารถบอกได้มีปัญหาเหมือนกับ C ++ ในเรื่องนี้

ใช่ C # มีปัญหาเช่นเดียวกับ C ++ แต่ก็ยังมีอีกมาก

ตัวอย่างเช่นรับข้อความนี้จาก Shawn Hawgraves:

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

มัน "ง่ายพอ" เพื่อให้แน่ใจว่าสิ่งนี้จะเกิดขึ้นใน C ++ อย่างไรก็ตามในC #นั่นเป็นเรื่องยากที่จะจัดการ ขอบคุณ JIT

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

JIT ไม่ได้กำหนดไว้เพราะคุณควบคุมมันได้น้อยมาก นี่คือหนึ่งในสิ่งที่คุณยอมแพ้ในการใช้ CLR

และพระเจ้าช่วยคุณถ้าคนคนหนึ่งกำลังใช้. NET 4.0 ในการรันเกมของคุณในขณะที่คนอื่นกำลังใช้ Mono CLR (แน่นอนว่าใช้ไลบรารี NET) แม้แต่. NET 4.0 กับ. NET 5.0 อาจแตกต่างกัน คุณเพียงแค่ต้องการควบคุมรายละเอียดระดับต่ำของแพลตฟอร์มเพื่อรับประกันสิ่งนี้

คุณควรจะสามารถหนีด้วยคณิตศาสตร์จุดคงที่ แต่นั่นเป็นเรื่องของมัน


นอกเหนือจากวิชาคณิตศาสตร์แล้วมีอะไรอีกที่แตกต่างออกไป? สันนิษฐานว่าการกระทำ "อินพุต" กำลังถูกส่งเป็นการกระทำเชิงตรรกะใน rts เช่นย้ายหน่วย "a" ไปยังตำแหน่ง "b" ฉันสามารถเห็นปัญหาเกี่ยวกับการสร้างตัวเลขสุ่ม แต่แน่นอนว่าต้องส่งเป็นอินพุตจำลองด้วยเช่นกัน
ลุ

@LukeN: ปัญหาคือตำแหน่งของ Shawn อย่างมากแสดงให้เห็นว่าความแตกต่างของคอมไพเลอร์สามารถมีผลกระทบที่แท้จริงกับคณิตศาสตร์จุดลอยตัว เขาจะรู้มากกว่าฉัน ฉันแค่คาดการณ์คำเตือนของเขาออกไปสู่อาณาจักรของการรวบรวม / ตีความ JIT และ C #
Nicol Bolas

C # มีการบรรทุกเกินพิกัดของผู้ปฏิบัติงานและยังมีประเภทในตัวสำหรับคณิตศาสตร์จุดคงที่ อย่างไรก็ตามสิ่งนี้มีปัญหาเช่นเดียวกับการใช้int- ฉันจะทำอย่างไรกับมันได้อย่างไร
BlueRaja - Danny Pflughoeft

1
> คุณคิดว่าจะเกิดอะไรขึ้นหากล่ามเรียกใช้รหัสของคุณ> ตีความหนึ่งครั้ง แต่จากนั้น JIT จะเป็นครั้งที่สองหรือไม่ หรือบางทีมันอาจตีความมันสองครั้งในเครื่องของคนอื่น แต่ JIT ทำมันหลังจากนั้น? 1. รหัส CLR จะถูก jitted เสมอก่อนที่จะดำเนินการ 2. . net ใช้ IEEE 754 สำหรับการลอยตัวแน่นอน > JIT ไม่ได้ถูกกำหนดเพราะคุณควบคุมมันได้น้อยมาก ข้อสรุปของคุณเป็นสาเหตุที่อ่อนแอมากของข้อความเท็จเท็จ > และพระเจ้าช่วยคุณได้ถ้ามีใครคนหนึ่งกำลังใช้. NET 4.0 ในการรันเกมของคุณ> ในขณะที่คนอื่นกำลังใช้ Mono CLR (โดยใช้หลักสูตร. NET ไลบรารี>>) Even .NET
Romanenkov Andrey

@ Romanenkov: "ข้อสรุปของคุณค่อนข้างอ่อนแอสาเหตุของการเท็จเท็จ" โปรดบอกฉันว่าอะไรเป็นคำเท็จและทำไมเพื่อให้พวกเขาสามารถแก้ไขได้
Nicol Bolas

1

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

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


0

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

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

การประสานข้อมูลเป็นกุญแจสำคัญแม้ว่า


-2

คุณทำให้พวกเขากำหนดขึ้น สำหรับตัวอย่างที่ยอดเยี่ยมดูการนำเสนอของ Dungeon Siege GDCว่าพวกเขาสร้างสถานที่ในเครือข่ายโลกได้อย่างไร

ยังจำได้ว่าระดับที่ใช้กับเหตุการณ์ 'สุ่ม' เช่นกัน!


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