สิ่งที่ทำให้ MMORPG ต่างจากเกมผู้เล่นคนเดียวคือเซิร์ฟเวอร์ที่อยู่เบื้องหลังทุกสิ่งที่คุณเห็น ในบันทึกการพัฒนา (devlog) ตอนแรกของ Ancient Online: Remastered นี้ เราจะอธิบายว่าเรากำลังสร้าง MMORPG ด้วย Unreal Engine 5.8 อย่างไร: งานถูกแบ่งระหว่างไคลเอนต์กับเซิร์ฟเวอร์อย่างไร โลกถูกจำลองอย่างไร และเราแก้ไขโลกผืนเดียวที่เชื่อมต่อกันทั้งหมดแบบสด ๆ ได้อย่างไร
สองส่วน: ไคลเอนต์และเซิร์ฟเวอร์
Ancient Online ประกอบด้วยซอฟต์แวร์สองส่วนที่แยกจากกัน:
- ไคลเอนต์เขียนด้วย C++ บน Unreal Engine 5.8 การเรนเดอร์ เสียง อินเทอร์เฟซ และอินพุตเป็นหน้าที่ของส่วนนี้
- เซิร์ฟเวอร์เป็นอิสระจาก Unreal: เราเขียนขึ้นใหม่ตั้งแต่ศูนย์ด้วย C++23 กติกาทั้งหมดของเกมทำงานที่นี่
ทำไมเราจึงเขียนเซิร์ฟเวอร์แยกต่างหากแทนที่จะเขียนไว้ในเอนจิน? เพราะสิ่งที่เซิร์ฟเวอร์ MMORPG ต้องการนั้นต่างจากสิ่งที่เอนจินเกมต้องการ: ไม่มีกราฟิก แต่มีเอนทิตีนับพัน ข้อมูลที่ต้องคงอยู่ถาวร ระยะเวลาทำงานต่อเนื่องที่ยาวนาน และความจำเป็นที่ประสิทธิภาพต้องคาดการณ์ได้ เซิร์ฟเวอร์ที่แยกออกมาทำให้เราทำเฉพาะงานที่จำเป็นและควบคุมได้ทุกไบต์
เซิร์ฟเวอร์แบบ authoritative: ไม่ไว้ใจไคลเอนต์
กฎพื้นฐานของเราคือ: ไคลเอนต์เป็นฝ่ายอ้าง เซิร์ฟเวอร์เป็นฝ่ายตัดสิน
- การเคลื่อนที่: อินพุตของผู้เล่นถูกส่งไปยังเซิร์ฟเวอร์ และเซิร์ฟเวอร์เป็นผู้คำนวณตำแหน่ง ไคลเอนต์แสดงตำแหน่งที่เซิร์ฟเวอร์รายงานมาโดยใช้การประมาณค่าระหว่างจุดอย่างนุ่มนวล ดังนั้นไคลเอนต์ที่ “เทเลพอร์ตตัวเอง” หรือเดินทะลุกำแพงจึงไม่ได้ไปไหนเลยในสายตาของเซิร์ฟเวอร์
- การต่อสู้: ผลลัพธ์อย่างความเสียหาย การโจมตีโดน และการผลักกระเด็นคำนวณบนเซิร์ฟเวอร์ ตัวอย่างเช่น เซิร์ฟเวอร์เป็นผู้ตัดสินว่าการโจมตีคอมโบทำให้คู่ต่อสู้ล้มหรือไม่ แล้วกระจายผลให้ทุกคนพร้อมกัน
- เศรษฐกิจ: ไอเทม เงิน และธุรกรรมของร้านค้าเปลี่ยนแปลงเฉพาะบนเซิร์ฟเวอร์และในฐานข้อมูลเท่านั้น
ต้นทุนของแนวทางนี้คือต้องจัดการความหน่วงของเครือข่ายให้ดี ส่วนผลตอบแทนคือโลกที่โกงได้ยากขึ้นมากและทุกคนอยู่ภายใต้กติกาเดียวกัน
ลูปโลกที่ 25 Hz
เซิร์ฟเวอร์อัปเดตโลก 25 ครั้งต่อวินาที ในแต่ละสเต็ป AI ของมอนสเตอร์ การเคลื่อนที่ การต่อสู้ เอฟเฟกต์สกิล และสภาพอากาศล้วนเดินหน้าไปพร้อมกัน สเต็ปที่คงที่ทำให้การจำลองคาดการณ์ได้ และรับประกันว่าอินพุตเดียวกันจะให้ผลลัพธ์เดียวกันเสมอ
ผู้เล่นทุกคนไม่จำเป็นต้องรู้ทุกเรื่อง เซิร์ฟเวอร์แบ่งโลกออกเป็นกริด และส่งอัปเดตให้ผู้เล่นแต่ละคนเฉพาะเอนทิตีที่อยู่ในพื้นที่ที่เกี่ยวข้องของเขา (สิ่งที่อยู่ใกล้) วิธีนี้ทำให้ปริมาณข้อมูลบนเครือข่ายอยู่ในระดับที่เหมาะสมแม้ในเมืองที่มีผู้เล่นหนาแน่น
โปรโตคอลไบนารีน้ำหนักเบา
ระหว่างไคลเอนต์กับเซิร์ฟเวอร์ไม่มี JSON หรือ REST ทุกข้อความเป็นแพ็กเก็ตไบนารีที่มีโครงสร้างตายตัว ซึ่งประหยัดทั้งแบนด์วิดท์และเวลาของ CPU เมื่อเราเพิ่มระบบใหม่ (เช่น สภาพอากาศ การเคลื่อนที่ หรือบริการบัญชีในเกม) เราจะเขียนข้อตกลงแพ็กเก็ตแยกต่างหากที่มีหมายเลขเวอร์ชันสำหรับระบบนั้น และใช้ไฟล์เฮดเดอร์ร่วมกันเพื่อรับประกันว่าไคลเอนต์กับเซิร์ฟเวอร์ทำงานจากข้อตกลงเดียวกัน
การคงข้อมูล: บันทึกโดยไม่ให้เกมต้องรอ
ข้อมูลผู้เล่นอยู่ในฐานข้อมูล PostgreSQL แต่การให้ลูปโลกรอฐานข้อมูลในทุกสเต็ปนั้นยอมรับไม่ได้ การบันทึกจึงทำในเบื้องหลังด้วยการบันทึกแบบ write-behind: เซิร์ฟเวอร์โลกส่งการเปลี่ยนแปลงลงคิว (Redis) แล้วตัวเขียนเบื้องหลังจะบันทึกลงฐานข้อมูลเป็นชุด ความลื่นไหลของเกมจึงไม่ขึ้นกับความเร็วของฐานข้อมูล
แชนแนลและเซิร์ฟเวอร์ล็อกอิน
ผู้เล่นเชื่อมต่อกับเซิร์ฟเวอร์ล็อกอินก่อน ซึ่งดูแลการยืนยันบัญชี การเลือกตัวละคร และเซสชัน จากนั้นจึงย้ายไปยังหนึ่งในสี่แชนแนลเกม (CH1–CH4) สถานะปัจจุบันของแชนแนลแสดงอยู่ในหน้าสถานะเซิร์ฟเวอร์ของเว็บไซต์เกม
โลกผืนเดียวที่แก้ไขสดได้
โลกของ Ancient Online ออกแบบให้เป็นโลกผืนเดียวที่เชื่อมต่อกันทั้งหมด ไม่ใช่แผนที่แยกส่วนที่คั่นด้วยหน้าจอโหลด โลกถูกแบ่งเป็นเซลล์และโหลดด้วยการสตรีม
เนื้อหาของโลก (ภูมิประเทศ วัตถุ ตำแหน่งวางมอนสเตอร์) ไม่ได้เก็บไว้ในโค้ด แต่เก็บในฐานข้อมูลแบบมีเวอร์ชัน เราแก้ไขโลกนี้ได้ด้วยตัวแก้ไขโลกในเกม: การเปลี่ยนแปลงจะทำในฉบับร่างก่อน ผ่านการตรวจสอบ แล้วจึงเผยแพร่ การเผยแพร่แต่ละครั้งสร้างเวอร์ชันใหม่ และไคลเอนต์จะยืนยันว่าข้อมูลโลกที่ตัวเองมีอยู่ตรงกับของเซิร์ฟเวอร์ด้วยการเปรียบเทียบค่าไดเจสต์ หากไม่ตรงกัน ไคลเอนต์จะรอให้ข้อมูลอัปเดตก่อนจึงเข้าเกมต่อ
เควสต์: Lua ในฐานะภาษาสคริปต์
เควสต์และบทสนทนาของ NPC เขียนด้วย Lua 5.4 บนเซิร์ฟเวอร์ ทำให้เราพัฒนาและทดสอบเควสต์ได้โดยไม่ต้องคอมไพล์เซิร์ฟเวอร์ใหม่
ข้อความของผู้เล่นไม่เคยออกจากเซิร์ฟเวอร์ของเรา
เราไม่ใช้บริการแปลภายนอกสำหรับการแปลแชตในเกม เรารันโมเดลแปลภาษาแบบโลคัลที่ใช้เฉพาะ CPU บนเซิร์ฟเวอร์ของเราเอง ข้อความของผู้เล่นจะไม่ถูกส่งไปยัง API ภายนอกใด ๆ ด้วยวิธีนี้ ผู้เล่นที่ใช้ภาษาต่างกันจึงเข้าใจกันได้โดยที่ข้อความไม่เคยออกจากสตูดิโอ
ต่อจากนี้
ตอนที่สองของบันทึกการพัฒนาว่าด้วยการตัดสินใจของเราในการทำให้โลกเดียวกันเล่นได้ทั้งด้วยเมาส์ หน้าจอสัมผัส และเกมแพด หากอยากรู้จักสตูดิโอ อ่านบทความ Astronaut Entertainment คือใคร? ส่วนตัวเกม ดูหน้าเกม


