อินพุตฝั่งเซิร์ฟเวอร์


9

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

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

นี่คือแผนภาพความล่าช้าเพื่อช่วยให้คุณเข้าใจสิ่งที่ฉันหมายถึง: http://i.imgur.com/Prr8K.png

ฉันสามารถส่งแพ็กเก็ต "W Pressed" แต่ละเฟรมเพื่อให้เซิร์ฟเวอร์ประมวลผล แต่ดูเหมือนว่าจะเป็นวิธีแก้ปัญหาแบนด์วิดท์ที่มีราคาแพง

ความช่วยเหลือใด ๆ ที่ชื่นชม!

คำตอบ:


5

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

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

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

สิ่งที่ฉันคิดว่าควรจะเกิดขึ้นก็คือ

client sends a move + position update
server gets it t+latency time later
server verifies and sends out info to all clients
client receives this at (t+latency + latency)

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


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

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

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

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

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

0

ฉันเข้าใจคำถามของคุณดังนี้:

เซิร์ฟเวอร์ได้รับแพ็คเก็ตเมื่อฉันเริ่มกดปุ่ม 'ไปข้างหน้า' และแพ็กเก็ตอื่นเมื่อฉันเปิดตัวปุ่ม 'ไปข้างหน้า' ในที่สุด ดังนั้นการเคลื่อนไหวที่เกิดขึ้นจริงบนเซิร์ฟเวอร์จะเริ่มต้นและสิ้นสุดประมาณ 100 มิลลิวินาที 'สายเกินไป' ในเกมจริงกับสิ่งที่ผู้เล่นแสดงออกบนฝั่งไคลเอ็นต์ ดังนั้นหากผู้เล่นต้องการย้าย 10 วินาทีเขาอาจสิ้นสุดการเคลื่อนไหว 10.x วินาทีแทนตำแหน่งx >= 1ออนไลน์

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

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

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

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


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