ตัวอย่างเช่นเกม Flappy Bird ที่โด่งดังหรืออะไรก็ตามที่เรียงลำดับจริงๆคือผู้เล่น (ในกรณีนี้คือนกหรือกล้องที่คุณต้องการ) ก้าวไปข้างหน้าหรือเป็นโลกทั้งโลกที่เคลื่อนไหวไปข้างหลัง (นกเปลี่ยนตำแหน่ง Y และมี ตำแหน่ง X คงที่)
ตัวอย่างเช่นเกม Flappy Bird ที่โด่งดังหรืออะไรก็ตามที่เรียงลำดับจริงๆคือผู้เล่น (ในกรณีนี้คือนกหรือกล้องที่คุณต้องการ) ก้าวไปข้างหน้าหรือเป็นโลกทั้งโลกที่เคลื่อนไหวไปข้างหลัง (นกเปลี่ยนตำแหน่ง Y และมี ตำแหน่ง X คงที่)
คำตอบ:
ผมไม่เห็นด้วยเล็กน้อยกับคำตอบของฟิลิปป์ ; หรืออย่างน้อยก็มีวิธีที่เขานำเสนอมัน มันให้ความประทับใจว่าการเคลื่อนย้ายโลกรอบ ๆ ผู้เล่นอาจเป็นความคิดที่ดีกว่า เมื่อมันตรงกันข้าม ดังนั้นนี่คือคำตอบของฉันเอง ...
ตัวเลือกทั้งสองสามารถทำงานได้ แต่โดยทั่วไปแล้วมันเป็นความคิดที่ดีที่จะ "พลิกกลับฟิสิกส์" โดยการเคลื่อนย้ายโลกรอบ ๆ ผู้เล่นมากกว่าผู้เล่นทั่วโลก
โลกมักจะมีวัตถุมากมาย หลายอย่างถ้าไม่ใช่มากที่สุดคงที่หรือนอนหลับ ผู้เล่นจะมีวัตถุหนึ่งหรือค่อนข้างน้อย การเคลื่อนย้ายโลกทั้งใบไปทั่วเครื่องเล่นหมายถึงการเคลื่อนย้ายทุกอย่างในฉากยกเว้นผู้เล่น วัตถุคงที่, วัตถุนอนหลับ, วัตถุไดนามิกที่ใช้งาน, แหล่งกำเนิดแสง, แหล่งกำเนิดเสียง, ฯลฯ ; ทั้งหมดจะต้องถูกย้าย
นั่นคือ (เห็นได้ชัดว่า) มีราคาแพงกว่าการเคลื่อนไหวเฉพาะสิ่งที่เคลื่อนไหวจริง (ผู้เล่นและอาจเป็นอีกสองสามอย่าง)
การย้ายโลกรอบตัวผู้เล่นทำให้โลก (และทุกอย่างในนั้น) เป็นจุดที่สิ่งต่าง ๆ กำลังเกิดขึ้นอย่างแข็งขันที่สุด ข้อผิดพลาดหรือการเปลี่ยนแปลงใด ๆ ในระบบหมายความว่าอาจมีการเปลี่ยนแปลงทุกอย่าง นี่ไม่ใช่วิธีที่ดีในการทำสิ่งต่าง ๆ ; คุณต้องการให้มีการแยกข้อบกพร่อง / การเปลี่ยนแปลงเท่าที่จะทำได้เพื่อที่คุณจะไม่ได้รับพฤติกรรมที่ไม่คาดคิดจากที่อื่นที่คุณไม่ได้ทำการเปลี่ยนแปลง
นอกจากนี้ยังมีปัญหาอื่น ๆ อีกมากมายด้วยวิธีนี้ ตัวอย่างเช่นมันแบ่งสมมติฐานมากมายว่าสิ่งต่าง ๆ ควรทำงานในเครื่องยนต์อย่างไร คุณจะไม่สามารถใช้ไดนามิกRigidBody
สำหรับสิ่งอื่นใดนอกจากผู้เล่นตัวอย่างเช่น เป็นวัตถุที่มีสิ่งที่แนบมาซึ่งRigidBody
ไม่ได้ตั้งค่าเป็นจลนศาสตร์จะทำงานโดยไม่คาดคิดเมื่อตั้งตำแหน่ง / การหมุน / สเกล (ซึ่งคุณจะทำทุกเฟรมสำหรับทุกวัตถุในฉากยกเว้นผู้เล่น😨)
อืม ... ใช่และไม่มี ตามที่ระบุไว้ในคำตอบของฟิลิปส์ในประเภทอนันต์รองชนะเลิศของเกม (หรือเกมใด ๆ ที่มีพื้นที่ explorable ขนาดใหญ่ที่ไร้รอยต่อ) ไปไกลจากจุดกำเนิดในที่สุดก็จะแนะนำ FPPEs เห็นได้ชัด ( Floating-Point ข้อผิดพลาดแม่นยำ ) และต่อไปยังในที่สุด ล้นประเภทตัวเลขทั้งที่ทำให้เกมของคุณพังหรือทำให้เกมครอยแตกในโลกแห่งเกม ... บนสเตอรอยด์! 😵 (เพราะ ณ จุดนี้ FPPEs จะทำให้เกมนี้มีรอยแตก "ปกติ" แล้ว)
ไม่ทำและทำทั้งสองอย่าง! คุณควรให้โลกอยู่กับที่และขยับเครื่องเล่นไปรอบ ๆ แต่ "re-root" ทั้งผู้เล่นและโลกเมื่อผู้เล่นเริ่มห่างไกลจากรูท (ตำแหน่ง[0, 0, 0]
)ของฉาก
หากคุณรักษาตำแหน่งสัมพัทธ์ของสิ่งต่าง ๆ (ผู้เล่นไปทั่วโลก) และทำกระบวนการนี้ในการอัพเดตเฟรมเดียวผู้เล่น (จริง) จะไม่สังเกตเห็น!
ในการทำเช่นนั้นคุณมีสองตัวเลือกหลัก:
นี่คือตัวอย่างของกระบวนการนี้ในการดำเนินการ
หากคุณดูซอร์สโค้ดของ Unity พวกเขาใช้1e-5
( 0.00001
) เป็นพื้นฐานในการพิจารณาค่าทศนิยมสองค่า "เท่ากัน" ข้างในVector2
และVector3
(ประเภทข้อมูลที่รับผิดชอบตำแหน่งของวัตถุ [euler-] การหมุนและสเกล) เนื่องจากการสูญเสียความแม่นยำจุดลอยตัวเกิดขึ้นทั้งสองทางห่างจากศูนย์จึงปลอดภัยที่จะสมมติว่าสิ่งใดก็ตามที่อยู่ภายใต้1e+5
( 100000
) หน่วยห่างจากรากของฉาก / แหล่งกำเนิดนั้นปลอดภัยที่จะทำงานด้วย
แต่! ตั้งแต่...
... ถ้าอย่างนั้นก็เป็นความคิดที่ดีที่จะทำการรูทเครื่องใหม่เร็วกว่า / บ่อยกว่าเครื่องหมาย 100,000 หน่วย ตัวอย่างวิดีโอที่ฉันให้ดูเหมือนจะทำทุก ๆ 1,000 หน่วยเป็นต้น
ตัวเลือกทั้งสองทำงาน
แต่ถ้าคุณต้องการนักวิ่งที่ไม่มีที่สิ้นสุดอย่างแท้จริงคุณจะต้องให้ผู้เล่นอยู่กับที่และย้ายโลก มิฉะนั้นคุณจะได้รับผลกระทบมากที่สุดจากตัวแปรที่คุณใช้เพื่อจัดเก็บตำแหน่ง X ในที่สุดจำนวนเต็มจะล้นและตัวแปรจุดลอยตัวจะมีความแม่นยำน้อยลงซึ่งจะทำให้การเล่นเกมช้าลงหลังจากนั้นไม่นาน แต่คุณสามารถหลีกเลี่ยงปัญหานี้ได้โดยใช้รูปแบบขนาดใหญ่พอที่จะไม่มีใครประสบปัญหาเหล่านี้ภายในช่วงเวลาที่หนึ่งสามารถเล่นได้ในเซสชันเดียว (เมื่อผู้เล่นย้าย 1,000 พิกเซลต่อวินาทีจำนวนเต็ม 32 บิตจะล้นหลังจาก 49 วัน)
ดังนั้นสิ่งใดก็ตามที่ทำให้คุณมีแนวความคิดที่เข้าใจง่ายสำหรับคุณ
การสร้างคำตอบของ XenoRoแทนที่จะเป็นวิธีการรูทใหม่ที่อธิบายไว้เราสามารถทำได้ดังนี้
สร้างบัฟเฟอร์แบบวงกลมของชิ้นส่วนของแผนที่ที่ไม่มีที่สิ้นสุดของคุณซึ่งตัวละครของคุณเคลื่อนผ่านไปพร้อมกับตำแหน่งที่อัปเดตด้วยเลขคณิตแบบโมดูโล (ดังนั้นคุณจึงวิ่งไปรอบ ๆ บัฟเฟอร์แบบวงกลม) เริ่มแทนที่ส่วนของบัฟเฟอร์ของคุณทันทีที่ตัวละครของคุณออกจากก้อน สมการอัปเดตผู้เล่นจะเป็นดังนี้:
player.position = (player.position + player.velocity) % worldBuffer.width;
นี่เป็นตัวอย่างของสิ่งที่ฉันพูดถึง:
นี่คือตัวอย่างของสิ่งที่เกิดขึ้นในตอนท้าย
ด้วยวิธีนี้คุณไม่ได้ทำงานเป็นข้อผิดพลาดที่มีความแม่นยำที่เคย แต่คุณอาจต้องการที่จะทำให้บัฟเฟอร์ที่มีขนาดใหญ่มากถ้าคุณตั้งใจจะทำเช่นนี้ใน 3 มิติมุมมองที่มีระยะทางไกลมาก (ตามที่คุณยังจะต้องสามารถที่จะดูไปข้างหน้าของตัวเอง ) หากเครื่องปัดนกขนาดเล็กของคุณอาจจะมีขนาดใหญ่เท่าที่มันจะต้องมีฉากเดียวสำหรับหน้าจอเดียวและบัฟเฟอร์ของคุณอาจมีขนาดเล็กมาก
โปรดทราบว่าคุณจะเริ่มต้นที่จะได้รับการทำซ้ำผลกับการใด ๆ PRNG และจำนวนสูงสุดของลำดับที่ไม่ซ้ำของคนรุ่น PRNG เป็นปกติจะน้อยกว่าความยาวของธาร (ที่ 2 จำนวนบิตที่ใช้ภายใน) กับmerzenne Twisterนี้ไม่ได้ มากของปัญหาในขณะที่มันใช้ 2.5K ของรัฐภายใน แต่ถ้าคุณใช้แตกต่างเล็ก ๆ คุณมี 2 ^ 127-1 ซ้ำสูงสุดก่อนที่จะทำซ้ำ (หรือแย่ลง) นี้เป็นยังคงเป็นจำนวนมากอย่างไรก็ตามทางดาราศาสตร์ คุณสามารถแก้ไขปัญหาช่วงเวลาการทำซ้ำได้แม้ว่า PRNG ของคุณจะมีช่วงเวลาสั้น ๆ ผ่านฟังก์ชั่นการผสมหิมะถล่มที่ดีสำหรับเมล็ดพันธุ์
ตามที่ได้รับการถามและยอมรับแล้วมันขึ้นอยู่กับขอบเขตและสไตล์ของเกมของคุณ แต่เนื่องจากไม่ได้กล่าวถึง: FlappyBird ย้ายสิ่งกีดขวางผ่านหน้าจอแทนที่จะเป็นผู้เล่นทั่วโลก
Spawner วางวัตถุบนหน้าจอด้วยความเร็วคงที่ในVector2.left
ทิศทางที่กำหนด