ฉันรู้ว่าการตั้งค่าผู้เล่นหลายคนที่เรียบง่ายของฉันอาจไม่ใช่ความคิดที่ดี แต่ทำไม?


11

ฉันกำลังสร้าง MOBA ตัวเล็ก ๆ ง่ายๆเพื่อความสนุกสนาน ฉันทำทุกอย่างที่ผู้เล่นคนเดียวแล้วฉันก็รู้ว่า "โอ้ฉันน่าจะเพิ่มหลายคนเหรอ"

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

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

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

ดังนั้นโดยทั่วไป:

  • ผู้เล่นคนที่ 1 ร่ายคาถาเพื่อให้เขาเคลื่อนที่เร็วขึ้น 100% เป็นเวลาหกวินาที
  • ลูกค้าในพื้นที่ของผู้เล่น 1 เพิ่มบัฟนั้นไปยังวัตถุหน่วยของเขา
  • ลูกค้าของผู้เล่น 1 ส่งข้อความไปยังเซิร์ฟเวอร์ว่า "เฮ้ฉันเพิ่งเสกคาถานี้"
  • เซิร์ฟเวอร์ทำให้แน่ใจว่าเขามีมานามากพอที่จะใช้คาถานั้นและถ้าเป็นเช่นนั้นจะเพิ่ม buff นั้นลงในสำเนาของเซิร์ฟเวอร์ของวัตถุหน่วย
  • เซิร์ฟเวอร์ส่งข้อความถึงลูกค้ารายอื่นว่า "เฮ้คนนี้เพิ่งเสกคาถานี้"
  • ลูกค้าอื่น ๆ ทุกคนจะได้รับข้อความและไปที่ "อ่าโอเคเจ๋ง" และเพิ่มบัฟนั้นไปยังออบเจคยูนิตในพื้นที่ของตนสำหรับผู้เล่นนั้น

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

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


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

1
สิ่งที่ยอดเยี่ยมคือพวกเราที่เหลือมีความหวังอย่างสมเหตุสมผลว่าเครือข่ายนั้นไม่ยาก มันทำได้
ashes999

คำตอบ:


12

นอกจากคำตอบของ Byte56 แล้วยังมีอีกสองสิ่งที่ต้องพิจารณา:

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

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

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

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

สำหรับแนวคิดเพิ่มเติมฉันแนะนำให้เรียกดูบทความอื่น ๆ ในลิงค์ที่สองนั้น

โชคดี!


6

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

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

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


5

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

สมมติว่าทุกคนทำหน้าที่แพ็คเก็ตทันทีที่มาถึง

@ Time 0 (wall time), Player 1 puts up a shield   (Message has been sent, but not received by anyone)
@ Time 1, Player 2 shoots player 1   (Message has been sent, but not received by anyone)

สมมติว่าเวลา 0 (T0) และ T1 อยู่ใกล้กัน

สิ่งที่เกิดขึ้นต่อไปขึ้นอยู่กับผู้ที่กำลังมองหาสิ่งนี้และตามลำดับที่แพ็กเก็ตมาถึงบนเซิร์ฟเวอร์ เซิร์ฟเวอร์ควรมีคำพูดสุดท้าย หากเซิร์ฟเวอร์ได้รับแพ็คเก็ตตามลำดับที่ระบุข้างต้นเซิร์ฟเวอร์จะใช้เกราะก่อนที่จะยิงและผู้เล่น 1 (P1) จะอยู่รอด จากมุมมองของ P1 เมื่อวางโล่ตัวเองเขาจะเห็นเกราะก่อนที่จะยิงและเอาชีวิตรอด แต่แล้ว P2 ล่ะ พวกเขาจะเห็นการยิงทันทีเพราะพวกเขายิง แต่พวกเขาจะเห็นเกราะก่อนหรือไม่ ถ้า(T0 + latency between P1 and the server + the latency between the server and P2) > T1เกราะจะขึ้นมาหลังจากการยิงและ P2 จะคิดว่ากระสุนของพวกเขาฆ่า P1 แล้ว เซิร์ฟเวอร์จะต้องแก้ไขสถานการณ์นี้อย่างใด

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

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

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

เวลาสนุกใช่มั้ย ไม่ว่าคุณจะทำอะไรลงไปมันก็จะช่วยให้คุณตระหนักถึงปัญหาเรื่องเวลา

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