ฉันจะซิงค์สถานะเกมแบบผู้เล่นหลายคนได้อย่างมีประสิทธิภาพกว่าการอัพเดทแบบเต็มได้อย่างไร


10

ฉันเคยทำการเข้ารหัสเครือข่ายเกมมาก่อน แต่ส่วนใหญ่ใช้ TCP สำหรับเกมโดยไม่ต้องใช้เวลาจริง ฉันกำลังทำงานกับเกม 2D Java ที่มีผู้เล่นหลายคนบนเครือข่าย เพื่อการเรียนรู้ฉันต้องการทำสิ่งนี้ด้วยตัวเองโดยไม่มี API เครือข่ายที่มีอยู่

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

มีวิธีที่มั่นคงที่คุณเคยใช้มาก่อนในการส่งการเปลี่ยนแปลงในสถานะและมีความแตกต่างมากพอในการปฏิบัติงานที่มีค่างานพิเศษหรือไม่


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

คำตอบ:


10

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

ฉันเองประสบความสำเร็จมากขึ้นกับรุ่นต่อไปนี้:

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

สิ่งนี้ได้ให้ประสิทธิภาพที่ดีสำหรับฉันกับโลกของเกมที่ค่อนข้างใหญ่

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


6

การซิงโครไนซ์มักจะแบ่งออกเป็นสองส่วน: ส่วนเพิ่มและแบบสัมบูรณ์

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

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

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

การบรรจุข้อมูลก็มีความสำคัญเช่นกัน คุณสามารถส่งประมาณ 1,400 ไบต์ (ขึ้นอยู่กับการกำหนดค่านี้เป็นค่าเริ่มต้น) ในแพ็คเกจ UDP หนึ่งซึ่งมักจะมีส่วนหัวไม่กี่ไบต์ ดังนั้นคุณสามารถอัปเดตตำแหน่ง 50-100 ยูนิตในแพ็คเกจเดียวได้อย่างง่ายดาย


ขอบคุณสำหรับคำแนะนำ Matzi ฉันยังคงใช้งานเซิร์ฟเวอร์และไคลเอนต์อยู่ แต่ฉันจะกลับมาตรวจสอบอีกสองสามวันและอาจยอมรับคำตอบของคุณ
Haz

ขอให้โชคดีกับคุณ! ;)
Matzi

1

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

นี้โพสต์ #AltDevBlogADayครอบคลุมบางแง่มุมของวิธีการนี้ใน RTS ที่ทันสมัย (โดยเฉพาะวิธีการตรวจสอบเมื่อลูกค้าของคุณเริ่มต้นทำงานเกม "แตกต่าง".)

จำไว้ว่าให้เรียบง่ายจนกว่าจะพิสูจน์เป็นอย่างอื่น :)


1
เหล่านี้เป็นสิ่งที่ดีอ่านจาก dev ของ Factorio ซึ่งใช้วิธีการนี้และคำแนะนำที่ซับซ้อนของวิธีการนี้ แต่ยังแสดงให้เห็นว่ามันจะทำงานได้: factorio.com/blog/post/fff-76 factorio.com/blog/post/fff -147 factorio.com/blog/post/fff-188
AaronLS
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.