วิธีการจัดการรถปิคอัพจำนวนมากในเกม MMO


26

เกมเช่น Minecraft หรือเกม MMO ใด ๆ ที่มีรถปิคอัพจัดการกับมันได้อย่างไร

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

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

คำถามจริงของฉันคือ MMO อื่นมีวิธีแก้ไขปัญหานี้อย่างไร


9
นอกจากนี้ในบริบทของ Minecraft หลังจากมีจำนวนรายการใกล้กันพอสมควร (3+ ของรายการเดียวกันใน blockspace เดียวกัน) เซิร์ฟเวอร์จะแทนที่ 3 อินสแตนซ์ที่มีอินสแตนซ์ที่จัดกลุ่มที่มีประเภทบล็อก ( minecraft:dirt) และการนับ (30) ดังนั้นเมื่อผู้เล่นอยู่ใกล้พอที่จะหยิบมันขึ้นมามันก็แค่เพิ่มการนับให้มากที่สุดเท่าที่จะทำได้ไปยังคลังของผู้เล่น หากผู้เล่นมีเพียงห้องสำหรับ 6 รายการและสแต็ค 30 อยู่บนพื้นดินผู้เล่นจะได้รับ 6 และสแต็คในการนับพื้นดินลดลงถึง 24
Zymus

6
@Zymus เป็นเรื่องน่าสังเกตว่าจริง ๆ แล้วประสิทธิภาพการทำเครื่องหมายลดลงสำหรับรายการที่มีจำนวนลดลงเนื่องจากพวกเขากำลังมองหาสิ่งที่อยู่ใกล้เคียง
user253751

มีอ่านผ่านen.wikipedia.org/wiki/Occlusion_culling
RJFalconer

คำตอบ:


48

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

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


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

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

ใช่การรวมวัตถุเป็นสิ่งจำเป็นในสถานการณ์นี้ :) โอเคขอบคุณมาก!
Alakanu

3
@Alakanu คุณสามารถตรวจสอบแนวคิด "Loaded Chunks" ของ Minecraft สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีที่คำตอบนี้นำไปใช้กับเกมนั้น
T. Sar - Reinstate Monica

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

22

คุณมีสองสิ่งที่แตกต่างกันมากในการจัดการ:

  1. เซิร์ฟเวอร์ต้องจัดการทั้งโลกในลักษณะที่มีสิทธิ์ เพื่อการสื่อสารกับลูกค้า N (ที่ N คือ "ใหญ่") เป็นสิ่งที่จำเป็น

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

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

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

ลูกค้าไม่ได้สนใจเช่นกันเนื่องจากนี่เป็นเพียงแค่อาหารตาที่ลูกค้าสามารถแต่งหน้าได้ทันที

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

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

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

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

แน่นอนว่าคุณสามารถแบ่งพาร์ติชั่นย่อยในเซลล์ของคุณและใช้บางอย่างที่ยอดเยี่ยม ใช้ kd-Tree ถ้าคุณต้องการ แต่อย่าคาดหวังว่าจะได้กำไรมาก คุณสามารถตัดสิ่งต่าง ๆ ด้วยแมนฮัตตัน distace หรือคุณสามารถเรียงลำดับสิ่งของของคุณในตารางเล็ก ๆ ของคุณเอง ... แต่ทำไม?

การตรวจสอบระยะทาง (ระยะทางกำลังสองจริง ๆ แต่ก็เหมือนกับคุณ) เป็นเพียงการคูณสองแบบและการเพิ่ม (ปรับให้เหมาะกับ MUL, MADD ดังนั้นเพียงแค่สองการดำเนินการ) ตามด้วยการย้ายสาขาหรือตามเงื่อนไข มันเร็วพอ ๆ กับการปฏิบัติการอื่นใดที่ไม่ตัดเซลล์ตารางทั้งหมดในเวลาเดียวกัน อันที่จริงนี่คือสิ่งที่คุณสามารถทำได้บน GPU ...

ดูว่าคุณจะมีสองสามร้อยหรืออย่างน้อยสองสามพันตรวจสอบระยะทางกับตำแหน่งเดียวกัน (ระยะทาง squared ทำงานได้ดี) คุณไม่มีปัญหามากเพียงแค่ทำการคำนวณนั้นมากยิ่งขึ้นเพราะมันค่อนข้างแคช - การวนซ้ำที่เป็นมิตรกับหน่วยความจำที่ต่อเนื่องและด้วยการเคลื่อนไหวแบบมีเงื่อนไข สิ่งที่ชอบ rot = r[i] + 1; r[i] = ((dx*dx+dy*dy) < DIST_SQ) ? rot : r[i];(pseudocode) นั่นคือการวนซ้ำหนึ่งครั้งในอาร์เรย์ที่มีค่าไม่กี่ร้อยต่อเฟรม คอมพิวเตอร์ไม่สนใจการทำเช่นนั้นมันโหลดและต่อเนื่องกันได้ง่าย ALU ง่ายไม่มีสาขาและมีการทำซ้ำเพียงสองสามพันครั้ง

สิ่งนี้ (หลายต่อหนึ่ง) ไม่ได้เป็นปัญหาระดับเดียวกัน (หลายต่อหลาย) เช่นเดียวกับบนเซิร์ฟเวอร์ จริงๆแล้วลูกค้าไม่ใช่ปัญหา


ฉันขอโทษฉันคิดว่ามันชัดเจนว่าฉันกำลังพูดถึงลูกค้าเมื่อฉันเริ่มพูดคุยของอัตราเฟรม
Alakanu

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

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

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

2
@Alakanu คุณใช้เวลาจำนวนมากในการบ่นกับคนที่พยายามช่วยเหลือคุณ ขอให้โชคดี
David Richerby

2

@ T.Sar เขียนความคิดเห็นที่คุณควรดูในแนวคิด Minecrafts "load chunk" สำหรับข้อมูลเพิ่มเติม ถ้าเป็นเช่นนั้นโปรดระวังว่ามันค่อนข้างซับซ้อนใน Minecraft เนื่องจากผู้คนสร้างเครื่องจักรในเกม

เวอร์ชันที่ง่ายมากดังต่อไปนี้:

โลกแบ่งออกเป็นพื้นที่สี่เหลี่ยม (ชิ้น) ใน Minecraft มีการแบ่งส่วนสูง แต่ mmos ส่วนใหญ่ไม่ต้องการสิ่งนั้น

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

ใน Minecraft พื้นที่นั้นมีขนาด 16x16 ช่วงตึกและลูกค้ารู้พื้นที่ประมาณ 9x9 แห่งและมี 4 ภูมิภาคในแต่ละทิศทาง (4 ภูมิภาคตะวันออก + ผู้เล่นภูมิภาคอยู่ใน +4 ภูมิภาคตะวันตก = 9 ภูมิภาคทั้งหมดทิศเหนือ / ทิศใต้เหมือนกัน)

ไม่มีอะไรน่าอัศจรรย์เกี่ยวกับตัวเลขเหล่านี้ใช้สิ่งที่สมเหตุสมผลในเกมของคุณ

ลูกค้าทำสิ่งเคลื่อนไหวภายในบริเวณนี้เท่านั้น เซิร์ฟเวอร์จะคำนวณสิ่งต่าง ๆ เช่นมอนสเตอร์ที่หลงทางในภูมิภาคที่อยู่ใกล้กับผู้เล่นบางคน

เมื่อผู้เล่นเดินไปรอบ ๆ ในภูมิภาคไม่มีอะไรพิเศษเกิดขึ้นเมื่อพวกเขาข้ามเส้นขอบภูมิภาค จากนั้นลูกค้าจะต้องถามเซิร์ฟเวอร์เกี่ยวกับภูมิภาคที่เห็นตอนนี้

ไม่มีอะไรผิดปกติกับการมีข้อ จำกัด ของภาพเคลื่อนไหวหลายระดับ ตัวอย่างเช่นรายการเคลื่อนไหวลดลงในพื้นที่ 3x3, มอนสเตอร์หลงทางในพื้นที่ 5x5 และเพียงแค่แสดงภูมิทัศน์ในพื้นที่ 9x9

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


ระยะทางในการดึงสามารถปรับได้ แต่ในกรณีนี้ 8 ชิ้นคือ 9x9 และเป็นการตัดสินใจฝั่งไคลเอ็นต์มันสามารถแจ้งให้เซิร์ฟเวอร์ทราบถึงสิ่งที่เร่งความเร็ว (ดังนั้นเซิร์ฟเวอร์จะไม่ส่งข้อมูลที่ลูกค้าจะไม่แสดง) นอกจากนี้ ... Doom และ Quake ไม่ได้แก้ปัญหาเกี่ยวกับการแสดงผลที่เหมาะสมเท่านั้น?
SparK

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