ขณะนี้ฉันกำลังทำงานบน platformer ที่มีผู้เล่นหลายคนค่อนข้างง่าย ฉันอ่านบทความเกี่ยวกับเทคนิคต่าง ๆ ที่ใช้ในการซ่อนเวลาแฝงอยู่ แต่ฉันก็ยังไม่เข้าใจแนวคิดบางอย่าง ฉันพบว่าหัวข้อน่าสนใจมากและต้องการลองใช้ความคิดด้วยตัวเอง แต่ฉันคิดว่าการขอแลกเปลี่ยน gamedev จะมีประสิทธิภาพมากขึ้นสำหรับคำถามของฉัน ฉันจะพยายามอย่างดีที่สุดเพื่ออธิบายสถานการณ์ปัจจุบันของฉันและคำถามใดที่เกิดขึ้นระหว่างทาง
ตอนนี้ฉันต้องการซิงค์ผู้เล่นคนเดียวกับเซิร์ฟเวอร์เท่านั้น ในทางทฤษฎีผมสันนิษฐานว่าผู้เล่นคนเดียวที่มีการคาดการณ์ฝั่งไคลเอ็นต์จะไม่ต้องการการแก้ไขเซิร์ฟเวอร์เนื่องจากไม่มีปัจจัยภายนอกที่มีอิทธิพลต่อการเคลื่อนไหวของเขา ดังนั้นต้นแบบของฉันในปัจจุบันมีผู้เล่นเพียงคนเดียวที่ซิงค์กับเซิร์ฟเวอร์โดยไม่ต้องทำการแก้ไขเซิร์ฟเวอร์
หากคุณคุ้นเคยกับระบบเครือข่ายเกมฉันคิดว่าคุณอาจข้ามส่วนบริบทแม้ว่าฉันอาจทำสิ่งผิดปกติไปพร้อมกัน
ลูปไคลเอ็นต์ (หนึ่งครั้งต่อเฟรมหนึ่งครั้งทุกๆ ~ 16.67ms)
ลูปไคลเอนต์แบบง่ายดูเหมือนว่า:
ตรวจสอบอินพุตภายใน (WASD) และจัดทำแพ็กเกจเป็นการกระทำ (เช่น
Type=MoveLeft, Time=132.0902, ID=15
) เราเก็บการกระทำที่บรรจุไว้เพื่อส่งในที่สุด นอกจากนี้เรายังนำการกระทำที่ต้องการไปใช้กับการจำลองทางฟิสิกส์ของเกมโดยตรง ตัวอย่างเช่นหากเรามีการMoveLeft
ดำเนินการเราจะใช้กำลังไปทางซ้ายกับความเร็วของผู้เล่นตรวจสอบเพื่อส่งการกระทำ เพื่อป้องกันการใช้แบนด์วิดท์ของลูกค้าที่ไม่เหมาะสมให้ส่งการกระทำที่ทำแพคเกจในช่วงเวลาที่แน่นอนเท่านั้น (เช่น 30ms)
ใช้การแก้ไขเซิร์ฟเวอร์ ณ จุดนี้จะจัดการกับเดลต้าและการแก้ไขที่ได้รับจากเซิร์ฟเวอร์และนำไปใช้กับการจำลองสถานการณ์ของเกม สำหรับคำถามนี้ไม่ได้ใช้
อัปเดตฟิสิกส์ท้องถิ่น ใช้วงฟิสิกส์ของผู้เล่นหลัก โดยพื้นฐานแล้วสิ่งนี้จะทำการทำนายการเคลื่อนไหวของผู้เล่น สิ่งนี้เป็นการเพิ่มแรงโน้มถ่วงให้กับความเร็วของผู้เล่นใช้ความเร็วของผู้เล่นกับตำแหน่งของเขาแก้ไขการชนกันตลอดทาง ฯลฯ ฉันควรระบุว่าการจำลองทางฟิสิกส์มักจะดำเนินการด้วยเดลต้าวินาทีคงที่ (เรียกหลายครั้งขึ้นอยู่กับวินาทีเดลต้าจริง) .
ฉันข้ามรายละเอียดเฉพาะบางอย่างเกี่ยวกับฟิสิกส์และส่วนอื่น ๆ เพราะฉันรู้สึกว่าพวกเขาไม่จำเป็นสำหรับคำถามนี้ แต่อย่าลังเลที่จะแจ้งให้เราทราบหากพวกเขาจะเกี่ยวข้องกับคำถาม
เซิร์ฟเวอร์ลูป (ทุก ๆ 15ms)
เซิร์ฟเวอร์ลูปที่เรียบง่ายดูเหมือนว่า:
จัดการกับการกระทำ ตรวจสอบแพ็คเกจการกระทำที่ได้รับจากลูกค้าและนำไปใช้กับการจำลองทางฟิสิกส์ของเซิร์ฟเวอร์ ตัวอย่างเช่นเราจะได้รับ 5
MoveLeft
กระทำและเราจะนำมาใช้บังคับกับความเร็ว 5 ครั้ง เป็นสิ่งสำคัญที่จะต้องทราบแพคเกจการดำเนินการทั้งหมดจะถูกดำเนินการในหนึ่ง "เฟรม"ตรงกันข้ามกับลูกค้าที่จะถูกนำไปใช้ทันทีที่การกระทำเกิดขึ้นอัปเดตลอจิกเกม เราอัปเดตฟิสิกส์ของเกมผู้เล่นที่เคลื่อนไหวและแก้ไขการชน ฯลฯ นอกจากนี้เรายังจัดแพคเกจเหตุการณ์สำคัญใด ๆ ที่เกิดขึ้นกับผู้เล่น (เช่นสุขภาพของผู้เล่นลดลงผู้เล่นเสียชีวิตเป็นต้น) ในภายหลัง
ส่งการแก้ไข เราเป็นประจำ (เช่นทุกๆ 35ms) ส่ง delta ไปยังผู้เล่นอื่น (เช่นตำแหน่งของผู้เล่นสุขภาพ ฯลฯ ) หากพวกเขาเปลี่ยนไปเมื่อเร็ว ๆ นี้ ส่วนนี้ไม่ได้ถูกนำไปใช้ในขณะที่ฉันต้องการให้ผู้เล่นคนเดียวทำการจำลองผลลัพธ์เดียวกันบนไคลเอนต์และเซิร์ฟเวอร์โดยไม่มีการแก้ไขเพื่อให้แน่ใจว่าการทำนายฝั่งไคลเอ็นต์ทำงานได้ดี
ปัญหา
ระบบปัจจุบันทำงานได้ดีภายใต้สถานการณ์ที่เรียบง่ายและฉันรู้สึกประหลาดใจอย่างยิ่งที่เห็นว่ามันให้ผลลัพธ์ที่คล้ายกันมากกับการเคลื่อนที่ในแนวนอนที่เรียบง่าย (ความไม่ถูกต้องเกิดจากข้อผิดพลาดแม่นยำของจุดลอยตัวฉันเชื่อว่า):
โปรดละเว้นกราฟิกต้นแบบ สี่เหลี่ยมสีขาว = ผู้เล่น, สี่เหลี่ยมสีแดง = อุปสรรค, สีน้ำเงิน = พื้นหลัง
อย่างไรก็ตามฉันได้รับข้อผิดพลาดในการซิงค์หลังจากทำการเคลื่อนไหวที่ไวต่อเวลาเช่นการกระโดดและการขยับเข้าใกล้สิ่งกีดขวางที่แยกได้:
ในทางทฤษฎีแล้วฉันคาดหวังว่าทั้งคู่จะได้ผลลัพธ์ที่เหมือนกันเสมอเนื่องจากไม่มีปัจจัยภายนอกที่ทำให้ลูกค้ามีอิทธิพลต่อตำแหน่งของเขา ในทางปฏิบัติฉันคิดว่าฉันเข้าใจปัญหา
ตั้งแต่การกระโดดรอบอุปสรรคเหมือนที่มากขึ้นอยู่กับระยะเวลาของการเล่นรูปแบบเล็ก ๆ ของเมื่อความเร็วจะถูกนำไปใช้กับตำแหน่งที่จะมี repercutions ผล (เช่นลูกค้าสามารถย้ายออกไปเพียงในเวลาที่จะหลีกเลี่ยงการปะทะกันกับที่ สิ่งกีดขวางในขณะที่เซิร์ฟเวอร์จะทำตามที่ได้รับแพคเกจการดำเนินการทั้งหมดในภายหลังและติดอยู่กับสิ่งกีดขวางเป็นระยะเวลาสั้น ๆ เปลี่ยนผลสุดท้าย) ความแตกต่างระหว่างวิธีที่ไคลเอ็นต์และเซิร์ฟเวอร์จัดการเป็นส่วนใหญ่ว่าไคลเอนต์จะดำเนินการทั้งหมดตามที่เกิดขึ้นในขณะที่เซิร์ฟเวอร์ดำเนินการทั้งหมดเป็น bulks ตามที่ได้รับ
คำถาม
บริบทที่ยาวนี้ในที่สุดนำไปสู่คำถามของฉัน (ขอบคุณสำหรับการอ่านที่ไกลขนาดนี้): เป็นเรื่องปกติที่ต้องมีการแก้ไขเซิร์ฟเวอร์แม้ว่าจะมีผู้เล่นเพียงคนเดียวที่ซิงค์กับเซิร์ฟเวอร์หรือฉันควรใช้เทคนิคบางอย่างเพื่อหลีกเลี่ยงการซิงโครไนซ์ ?
ฉันคิดถึงวิธีแก้ปัญหาที่เป็นไปได้บางอย่างซึ่งฉันไม่ค่อยสบายใจกับ:
ใช้การแก้ไขเซิร์ฟเวอร์ เพียงสมมติว่านี่เป็นพฤติกรรมปกติและแก้ไขข้อผิดพลาดเมื่อเกิดขึ้น ฉันต้องการใช้งานต่อไป แต่ฉันแค่ต้องการทำให้แน่ใจว่าสิ่งที่ฉันได้ทำไปนั้นเป็นที่ยอมรับ
ใช้เวลาของไคลเอ็นต์ที่ระบุเพื่อใช้การกระทำที่ต้องการ ฉันเดาว่านี่จะคล้ายกับการชดเชยความล่าช้าโดยต้อง "ย้อนเวลากลับไป" และตรวจสอบความเคลื่อนไหว ชนิดของการใช้การแก้ไขเซิร์ฟเวอร์ย้อนเวลากลับไปและดำเนินการต่อไปหลังจากนั้น ฉันไม่ชอบความคิดจริงๆ มันดูซับซ้อนทรัพยากรแพงและต้องใช้เวลาที่ลูกค้าไว้วางใจ (แม้ว่าฉันจะวางแผนเพื่อตรวจสอบว่าเวลานั้นดูค่อนข้างถูกกฎหมาย)
ถาม GameDevelopment StackExchange สำหรับไอเดียใหม่ยอดเยี่ยมที่จะแก้ไขปัญหาทั้งหมดของฉัน
ฉันเพิ่งเริ่มต้นในโลกของเครือข่ายเกมดังนั้นโปรดแก้ไข / วิจารณ์ / ดูถูกแนวคิดใด ๆ ข้างต้นหรือให้ความคิด / ทรัพยากรที่สามารถช่วยฉันได้ตลอดการเดินทางใน Wonderful World of Networking ให้อภัยฉันถ้าฉันสามารถหาคำตอบของฉันที่อื่นฉันล้มเหลวที่
ขอบคุณมากสำหรับช่วงเวลาอันมีค่าของคุณ