วิธีจัดการกับ Block World อย่าง Minecraft


9

ฉันต้องการเขียนเกมง่ายๆที่มีโลกบล็อกเหมือนกับใน Minecraft คำถามเชิงทฤษฎีของฉันคือวิธีที่ดีที่สุดในการจัดการข้อมูลบล็อกนี้ในระหว่างการเล่น ความคิดแรกของฉันคือชุดใหญ่ แต่จะทำให้หน่วยความจำหมดฉันคิดว่า บางทีฉันอาจต้องโหลดบล็อกที่อยู่ใกล้กับผู้เล่นเท่านั้น

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


2
Minecraft โหลดโลกในลูกบาศก์ที่ค่อนข้างใหญ่ที่เรียกว่า Chunks ไม่ใช่ทั้งหมดในคราวเดียว ฉันไม่แน่ใจรายละเอียดที่แน่นอน แหล่ง Minecraft นั้นถือได้ง่ายถ้าคุณต้องการดูว่ามันหายไปไหน
ratbum


ฉันรู้แล้วเกี่ยวกับชิ้นส่วนใน Minecraft แต่ก็ขอบคุณอยู่ดี
danijar

นี่เป็นคำถามที่ซับซ้อนไม่เหมาะกับขอบเขตของบล็อกนี้

คำตอบ:


9

มีวิธีการเก็บข้อมูลสำหรับเกมที่มีบล็อกอย่าง Minecraft หลายวิธี

วิธีที่ฉันเชื่อว่า Minecraft เป็นสิ่งที่ทำให้โลกแตกใน 16x16x256 ชิ้น ชิ้นรอบผู้เล่นจะถูกโหลดเข้าสู่หน่วยความจำเมื่อผู้เล่นเริ่มเกมแล้วด้ายพื้นหลังจะโหลดมากขึ้นเมื่อคุณเดินไปรอบ ๆ นี่คือวิดีโอที่แสดงให้เห็นว่ามัน: http://www.youtube.com/watch?v=oR_ZdJH9eho

อีกวิธีที่จะทำคือการแบ่งโลกออกเป็นออคทรี ไมเคิล Goodfellow เขียนบล็อกเกี่ยวกับการใช้ลูกบาศก์โลกที่มีโครงสร้างข้อมูลนี้: http://www.sea-of-memes.com/LetsCode1/LetsCode1.html Octree เป็นสิ่งที่ดีเพราะมันช่วยให้คุณได้รับแรงอัด แต่มันอาจจะยากกว่าถ้าใช้กับ Array

เกี่ยวกับการรักษา "สิ่งที่ต้องการในหน่วยความจำเท่านั้น" นี่เป็นเรื่องยากขึ้นเล็กน้อยเนื่องจากคุณต้องถามสิ่งที่ "จำเป็น" หากคุณมี NPC ที่อาศัยอยู่ในอีกส่วนหนึ่งของโลกด้วย AI ที่มีปฏิสัมพันธ์กับสภาพแวดล้อมคุณต้อง "โลก" จำนวนมากต้องอยู่ในความทรงจำ ข้อมูลโลก Voxel สามารถมีขนาดใหญ่มากได้อย่างรวดเร็วดังนั้นจึงเป็นการดีที่สุดที่จะพยายามรักษาจำนวนหน่วยความจำให้น้อยที่สุดเท่าที่จะทำได้ (IE มี NPC เพียงใกล้กับเครื่องเล่น)

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

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

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


ขอบคุณ! ไม่มีอะไรเกี่ยวกับ AI เพราะฉันเขียนไคลเอนต์สำหรับ MMO การคำนวณ NPC ทำโดยเซิร์ฟเวอร์ การเพิ่มหนึ่ง: ไม่ใช่ "ทุกบล็อคที่ไม่ล้อมรอบด้วยบล็อกที่ไม่โปร่งใสอื่น ๆ " เป็นสิ่งจำเป็นสำหรับเอ็นจิ้นกราฟิก หากมีถ้ำผู้เล่นจะไม่สามารถมองเห็นว่ามันไม่สำคัญ ;-)
danijar

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

3

ฉันอาจไม่มีวิธีที่ดีที่สุดในการอธิบาย แต่ฉันจะพยายาม

ฉันคิดว่าวิธีที่ดีที่สุดในการทำความเข้าใจวิธีทำให้มีประสิทธิภาพมากขึ้นคือการเข้าใจ Voxels Minecraft นั้นใช้ voxel เพียงแค่ใช้ลูกบาศก์แทนที่จะเป็นทรงกลม ฯลฯ เป็นต้น

โดยทั่วไป voxel เป็นรูปร่าง 3 มิติที่สามารถมีปริมาณที่เปลี่ยนแปลงแบบไดนามิกและเมื่อปริมาณมีการเปลี่ยนแปลงรูปร่างจึงไม่ ก้อนเป็นชุด x by x by x ชุดของ voxels ตัวอย่างเช่นคุณสามารถมีอันที่มี 16x16x16 voxels แล้วคุณสามารถมีจำนวน X จำนวน คุณจะมีระยะห่างที่กำหนดว่าหากผู้เล่นอยู่ไกลกว่า N ห่างจากกลุ่มใด ๆ อย่ารวมไว้ในการคำนวณของคุณ นี่คล้ายกับระยะการตัด แต่จะต้องใช้กับแต่ละอันด้วย ด้วยวิธีนี้คุณสามารถมีมันเพื่อให้คุณสามารถมีผู้เล่นของคุณอยู่ตรงกลางก้อนอัน, พูด, 3x3 ชุดของชิ้น

ดังนั้นสิ่งที่คุณควรมีคือคลาสสำหรับจัดการ Voxels แต่ละตัว เราจะเรียกมันว่า Voxel_cl และจากนั้นคุณจะมีคลาสเพื่อจัดการ chunk of voxels ที่เรียกว่า Chunk_cl และจากนั้นคุณจะมีระดับโลกที่สร้างชิ้นทั้งหมดที่จะสร้าง voxels ที่เรียกว่า World_cl

ดังนั้นแทนที่จะเป็นทุกอย่างที่มีขนาดใหญ่คุณจะมีชุดของ 9 ชิ้นในเวลาใดก็ได้และในชั้นชิ้นคุณจะมีชุดของ 4096 voxels

โปรดทราบว่านี่เป็นคำอธิบายที่ค่อนข้างง่าย ฉันกำลังทำงานบางอย่างโดยใช้ voxels ดังนั้นฉันคิดว่าฉันจะโยนในการป้อนข้อมูลของฉัน = -)

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ voxels ให้ตรวจสอบhttp://en.wikipedia.org/wiki/Marching_cubes


3
คิวบ์เดินขบวนเป็นเรื่องเกี่ยวกับการมองเห็น voxels และ Minecraft ก็ไม่ได้ใช้มัน มันเป็นเพียงแค่ดึงก้อนซึ่งเป็นสิ่งที่วงก้อนเป็นเรื่องเกี่ยวกับไม่ทำ
Nicol Bolas

ขอบคุณสำหรับคำอธิบาย! ฉันไม่เคยได้ยินเกี่ยวกับ Voxels มาก่อนและดูเหมือนว่าสำคัญมากสำหรับโครงการของฉัน แต่ฉันมีคำถามเหลือแล้ว
danijar

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

2
@danijar เพียงเล็กน้อยเรื่องย่อพิกเซลสั้นสำหรับ "องค์ประกอบภาพ", voxel ถูกสร้างขึ้นในลักษณะเดียวกันจาก "องค์ประกอบเสียง" ไม่ใช่ว่ามันสำคัญสำหรับทุกสิ่ง แต่เนื่องจากคุณไม่เคยได้ยินคำว่า voxel มาก่อนฉันคิดว่ามันอาจเป็นที่สนใจของคุณ
Daniel Carlsson

1

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

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