โปรโตคอลเกม RTS


18

ฉันคิดเกี่ยวกับเกม RTS สำหรับผู้เล่นหลายคน ส่วนที่ฉันไม่สามารถหลีกเลี่ยงได้คือการซิงค์การเคลื่อนที่ของยูนิต ถ้าฉันย้ายยูนิต A ไปที่จุด XY ฉันต้องสื่อสารกลับไปที่เซิร์ฟเวอร์ที่ถ่ายทอดไปยังไคลเอนต์อื่น

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

แก้ไข

นี่คือคำถามที่โพสต์ใหม่จาก StackOverflow ฉันพบว่าไซต์นี้น่าจะเป็นสถานที่ที่ดีกว่าสำหรับคำถาม

หนึ่งในคำตอบที่ดีกว่าจากโพสต์นั้น:

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


2
คำตอบนั้นขึ้นอยู่กับวิธีที่คุณต้องการใช้ ลูกค้า - ลูกค้าหรือลูกค้า - เซิร์ฟเวอร์ ไคลเอนต์ต่อเซิร์ฟเวอร์นั้นง่ายกว่า แต่ต้องใช้เซิร์ฟเวอร์ที่เชื่อถือได้
Cem Kalyoncu

คำตอบ:


25

คุณไม่ต้องการซิงค์ตำแหน่งของทุกหน่วยจากเซิร์ฟเวอร์กับลูกค้าแต่ละราย ที่จะเกิดขึ้นทางแบนด์วิธมากกว่าที่คุณต้องการ นอกจากนี้คุณยังต้องจัดการกับตำแหน่งหน่วย interpolating / การคาดการณ์ ฯลฯ เกือบจะไม่มีไคลเอนต์ / เซิร์ฟเวอร์การใช้งาน RTS ของมืออาชีพ!

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

ข้อเสียคือผู้เล่นทุกคนช้าเท่ากับผู้เล่นที่ช้าที่สุด - ถ้ามีใครตกหล่นในการส่งคำสั่งทุกคนจะต้องชะลอตัวลงและรอให้เขาทัน (ใน Starcraft 2 นี่คือ"XXX กำลังทำให้เกมช้าลงกล่องโต้ตอบ" )


ในความเป็นจริงมีอีกสิ่งหนึ่งที่มักจะทำ: ขจัดเซิร์ฟเวอร์ทั้งหมด ให้ไคลเอนต์ทุกคนส่งคำสั่งไปยังไคลเอนต์อื่น ๆ สิ่งนี้จะช่วยลดความล่าช้า(แทนที่จะเป็นคำสั่งที่มาจากคุณ -> เซิร์ฟเวอร์ -> คู่แข่งมันแค่ไปจากคุณ -> คู่ต่อสู้) และทำให้การเข้ารหัสง่ายขึ้นเนื่องจากคุณไม่จำเป็นต้องใช้รหัสเซิร์ฟเวอร์แยกต่างหากอีกต่อไป สถาปัตยกรรมประเภทนี้เรียกว่าpeer-to-peer (P2P)

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


การตั้งค่านี้(ส่งเฉพาะคำสั่งโดยใช้ P2P)เป็นวิธีการที่ทีเอสส่วนใหญ่รวมทั้งตาร์คราฟ, C & C และการทำงาน AoE และเป็นวิธีเฉพาะ AoE อาจจะสนับสนุนหน่วย 1500 ในการเชื่อมต่อ

(ภาพเครือข่ายใน AoE)

นี่คือเคล็ดลับเพิ่มเติมเล็กน้อยสำหรับการเขียน P2P RTS:

  • ด้วยเหตุผลที่ชัดเจนการตั้งค่านี้สามารถใช้งานได้หากเกมของคุณใช้เวลาคงที่ - คุณไม่ต้องการให้ผลลัพธ์ของการคำนวณขึ้นอยู่กับอัตราเฟรม! ขั้นตอนคงที่นั้นง่ายต่อการทำงานกับสิ่งต่าง ๆ ส่วนใหญ่ดังนั้นสิ่งนี้ไม่ควรเป็นปัญหา
  • ในการสั่งซื้อสำหรับการทำงานผลของทุกคำสั่งจะต้องกำหนดอย่างสมบูรณ์
    • นี่เป็นเรื่องง่ายถ้าคุณ จำกัด ระบบหนึ่งตัว (เช่น Windows 32 บิต) และบังคับให้ไคลเอนต์ทั้งหมดใช้โปรแกรมปฏิบัติการเดียวกัน: ตรวจสอบให้แน่ใจว่าเครื่องกำเนิดเลขสุ่มใด ๆ มีเมล็ดเดียวกันและถูกเรียกในลำดับเดียวกันเสมอ ต้องระมัดระวังมากเมื่อ iterating กว่าคอลเลกชันเรียงลำดับ ; เป็นต้น
    • นี่เป็นเรื่องยากมากหากคุณวางแผนที่จะทำให้เกมเล่นได้บนแพลตฟอร์มที่แตกต่างกันหรือ (ตามปกติในกรณีของ Linux) อนุญาตให้ไคลเอนต์รวบรวมรหัสด้วยตนเอง ไม่เพียง แต่เป็นระบบห้องสมุดที่แตกต่างกันรับประกันสวยมากที่จะใช้การใช้งานที่แตกต่างกันของrand(), cos()ฯลฯ แต่สวยมากทุกคณิตศาสตร์จุดลอยตัวเป็นไปไม่ได้(ดูที่นี่ , ที่นี่และที่นี่ ) ! ในกรณีดังกล่าวคุณอาจใช้งานไคลเอนต์ - เซิร์ฟเวอร์ดีกว่า
  • คุณจะต้องการส่งตำแหน่งทุกหน่วยออกไปเป็นระยะ ๆ อย่างน้อยในขณะที่ทำการดีบั๊กเพื่อตรวจจับข้อบกพร่อง desync (ซึ่งเชื่อฉันคุณจะมี) ไม่ว่าคุณจะทำเช่นนั้นในเกมสุดท้ายนั้นขึ้นอยู่กับคุณ - ฉันจะซิงค์อย่างน้อยบางยูนิต (หรือใช้การตรวจสอบบางอย่าง) เพื่อตรวจจับการพยายามแฮ็ค

โพสต์ที่ดี สิ่งเล็ก ๆ ที่ควรเพิ่มแม้คอมไพเลอร์ตัวเดียวกันจะทำการปรับแก้จุดบกพร่อง / รีลีสและแฟล็กอื่น ๆ อาจเปลี่ยนผลลัพธ์ได้ ระวัง!
ปีเตอร์Ølsted

14

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

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

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

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

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

สำหรับสิ่งที่ข้อความอาจมีลักษณะเช่น ฉันไม่ได้กังวลเกี่ยวกับประสิทธิภาพพิเศษเพราะมันเป็นเกมบนเครือข่ายเกมแรกของฉัน ฉันส่งคำสั่งเป็นสตริง คำสั่งจะมีรูปแบบดังนี้:"<player_id>:<command>:<parameters>"

"3:move:522:100:200"สำหรับตัวอย่างที่ประดิษฐ์คำสั่งย้ายอาจมีลักษณะเช่นนี้ หมายความว่าผู้เล่น3ต้องการmoveหน่วย522ถึง ( 100, 200)

"153238:3:move:522:100:200"เซิร์ฟเวอร์ผ่านคำสั่งไปยังลูกค้าทุกคนรวมทั้งคนหนึ่งที่ส่งมามีจำนวนเห็บที่แนบมาเช่นนี้

จากนั้นไคลเอนต์ทั้งหมดจะดำเนินการคำสั่งนี้เมื่อทำเครื่องหมายเลือก 153238


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

ใช่นั่นเป็นอีกวิธีที่จะทำ แต่ดูเหมือนว่าสำหรับฉันแล้วมันจะทำงานได้ดีกว่าในการผ่านสถานการณ์ของเกมไปรอบ ๆ มากกว่าจะเป็นแค่คำสั่ง เกมของฉันเรียบง่ายพอที่ทุกอย่างจะทำงานบนเครื่องไคลเอนต์แต่ละเครื่อง สำหรับ MMO หรืออย่าง Minecraft คุณไม่มีการจำลองทั้งหมดที่ทำงานบนฝั่งไคลเอ็นต์ดังนั้นคุณจะส่งผ่านเฉพาะข้อมูลที่เกี่ยวข้องกับลูกค้าแต่ละรายเท่านั้น
ฟิลิป
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.