อะไรคือความเคลื่อนไหวในนักวิ่งที่ไม่มีที่สิ้นสุด?


107

ตัวอย่างเช่นเกม Flappy Bird ที่โด่งดังหรืออะไรก็ตามที่เรียงลำดับจริงๆคือผู้เล่น (ในกรณีนี้คือนกหรือกล้องที่คุณต้องการ) ก้าวไปข้างหน้าหรือเป็นโลกทั้งโลกที่เคลื่อนไหวไปข้างหลัง (นกเปลี่ยนตำแหน่ง Y และมี ตำแหน่ง X คงที่)


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

คำตอบ:


146

ผมไม่เห็นด้วยเล็กน้อยกับคำตอบของฟิลิปป์ ; หรืออย่างน้อยก็มีวิธีที่เขานำเสนอมัน มันให้ความประทับใจว่าการเคลื่อนย้ายโลกรอบ ๆ ผู้เล่นอาจเป็นความคิดที่ดีกว่า เมื่อมันตรงกันข้าม ดังนั้นนี่คือคำตอบของฉันเอง ...


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


ประสิทธิภาพการสูญเสีย / เสีย:

โลกมักจะมีวัตถุมากมาย หลายอย่างถ้าไม่ใช่มากที่สุดคงที่หรือนอนหลับ ผู้เล่นจะมีวัตถุหนึ่งหรือค่อนข้างน้อย การเคลื่อนย้ายโลกทั้งใบไปทั่วเครื่องเล่นหมายถึงการเคลื่อนย้ายทุกอย่างในฉากยกเว้นผู้เล่น วัตถุคงที่, วัตถุนอนหลับ, วัตถุไดนามิกที่ใช้งาน, แหล่งกำเนิดแสง, แหล่งกำเนิดเสียง, ฯลฯ ; ทั้งหมดจะต้องถูกย้าย

นั่นคือ (เห็นได้ชัดว่า) มีราคาแพงกว่าการเคลื่อนไหวเฉพาะสิ่งที่เคลื่อนไหวจริง (ผู้เล่นและอาจเป็นอีกสองสามอย่าง)


การบำรุงรักษาและการขยาย:

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

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


ดังนั้นคำตอบคือให้ย้ายผู้เล่นเท่านั้น!

อืม ... ใช่และไม่มี ตามที่ระบุไว้ในคำตอบของฟิลิปส์ในประเภทอนันต์รองชนะเลิศของเกม (หรือเกมใด ๆ ที่มีพื้นที่ explorable ขนาดใหญ่ที่ไร้รอยต่อ) ไปไกลจากจุดกำเนิดในที่สุดก็จะแนะนำ FPPEs เห็นได้ชัด ( Floating-Point ข้อผิดพลาดแม่นยำ ) และต่อไปยังในที่สุด ล้นประเภทตัวเลขทั้งที่ทำให้เกมของคุณพังหรือทำให้เกมครอยแตกในโลกแห่งเกม ... บนสเตอรอยด์! 😵 (เพราะ ณ จุดนี้ FPPEs จะทำให้เกมนี้มีรอยแตก "ปกติ" แล้ว)


จริงการแก้ปัญหา:

ไม่ทำและทำทั้งสองอย่าง! คุณควรให้โลกอยู่กับที่และขยับเครื่องเล่นไปรอบ ๆ แต่ "re-root" ทั้งผู้เล่นและโลกเมื่อผู้เล่นเริ่มห่างไกลจากรูท (ตำแหน่ง[0, 0, 0])ของฉาก

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

ในการทำเช่นนั้นคุณมีสองตัวเลือกหลัก:

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

นี่คือตัวอย่างของกระบวนการนี้ในการดำเนินการ


แต่ไกลแค่ไหนไกลเกินไป?

หากคุณดูซอร์สโค้ดของ Unity พวกเขาใช้1e-5( 0.00001) เป็นพื้นฐานในการพิจารณาค่าทศนิยมสองค่า "เท่ากัน" ข้างในVector2และVector3(ประเภทข้อมูลที่รับผิดชอบตำแหน่งของวัตถุ [euler-] การหมุนและสเกล) เนื่องจากการสูญเสียความแม่นยำจุดลอยตัวเกิดขึ้นทั้งสองทางห่างจากศูนย์จึงปลอดภัยที่จะสมมติว่าสิ่งใดก็ตามที่อยู่ภายใต้1e+5( 100000) หน่วยห่างจากรากของฉาก / แหล่งกำเนิดนั้นปลอดภัยที่จะทำงานด้วย

แต่! ตั้งแต่...

  1. เป็นการเหมาะสมกว่าที่จะทำให้ระบบจัดการกระบวนการรูทใหม่เหล่านี้โดยอัตโนมัติ
  2. ไม่ว่าเกมของคุณจะมีอะไรก็ตามคุณไม่จำเป็นต้องมี "ส่วน" ต่อเนื่องของโลกที่จะกว้างถึง 100,000 หน่วย (เมตร [?])

... ถ้าอย่างนั้นก็เป็นความคิดที่ดีที่จะทำการรูทเครื่องใหม่เร็วกว่า / บ่อยกว่าเครื่องหมาย 100,000 หน่วย ตัวอย่างวิดีโอที่ฉันให้ดูเหมือนจะทำทุก ๆ 1,000 หน่วยเป็นต้น


2
ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท โปรดใช้การแชทนั้นแทนการโพสต์ความคิดเห็นเพิ่มเติมที่นี่
Alexandre Vaillancourt

> นั่นแพงกว่าการเคลื่อนย้ายสิ่งที่เคลื่อนไหวจริงๆ <มันคืออะไร? เมื่อเรนเดอร์คุณจะต้องทำการคูณเมทริกซ์กับเมทริกซ์กล้องบนวัตถุทั้งหมดการที่กล้องจับจ้องอยู่ที่ตัวตนจะมีราคาไม่แพงในลักษณะนี้
Matsemann

ช่วงเวลานั้นเมื่อการพัฒนาเกมกลายเป็นการพัฒนาที่เป็นเอกภาพ ...
LJ ᛃ

@Matsemann - ถ้าคุณเคยไปแชทคุณจะสังเกตเห็นว่านี่ไม่ใช่ประเด็นใหม่ ตามที่ได้อธิบายไปแล้วให้สร้างฉากแบบไม่เท่ากับ; พวกเขาแตกต่างกันและเกือบจะเป็นเรื่องอิสระและท่อ การทำกรอบอ้างอิงย้อนกลับในลักษณะที่วัตถุอยู่ในฉากจะหมายความว่าคุณจะมีกระบวนการที่หนักกว่าทั้งสองด้านแทนที่จะแสดงภาพ --- นอกจากนี้แม้ว่าประสิทธิภาพการซื้อขายจะเท่ากันในขณะที่คุณโต้แย้งปัญหาอื่น ๆทั้งหมดของการผกผันจะยังคงไม่ได้รับการแก้ไขทำให้วิธีการนั้นยังคงแย่กว่าการรูทใหม่
XenoRo

@LJ ᛃคำถามที่ถูกสร้างขึ้นมาเกี่ยวกับความสามัคคีโดยเฉพาะ (ดูแท็ก OP ก่อนที่จะดี Everhard ของ [IMHO defacing] แก้ไข) และเพื่อให้คำตอบที่ได้รับการปรับให้เหมาะสมกับสะท้อนให้เห็นว่า --- แต่นี่คือส่วนที่ดีที่สุด: ไม่ว่าจะเป็น Unity, Unreal, CryEngine, Source ฯลฯ ... เอ็นจิ้นที่ดีที่สุดและ / หรือได้รับความนิยมมากที่สุดทำงานในลักษณะนี้ (และพวกเขาทำได้ด้วยเหตุผล) ดังนั้นคำตอบไม่เพียง ได้อย่างสมบูรณ์แบบที่ถูกต้องในทั่วไป แต่จุดที่มีการทำอยู่ยังคงอยู่ที่จุดสุดยอดของความถูกต้อง โดยทั่วไปถ้าคุณสลับกรอบอ้างอิงฟิสิกส์คุณสามารถคาดหวังว่าจะพบปัญหาโดยเฉพาะกับวัตถุแบบไดนามิก
XenoRo

89

ตัวเลือกทั้งสองทำงาน

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

ดังนั้นสิ่งใดก็ตามที่ทำให้คุณมีแนวความคิดที่เข้าใจง่ายสำหรับคุณ


ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
Josh

1
ฉันไม่คิดว่ามันจะแก้ปัญหาอะไร แทนที่จะรักษาตำแหน่งของผู้เล่น (และกล้อง) คุณรักษาตำแหน่งการเลื่อนของโลก - มันแตกต่างกันอย่างไร?
Agent_L

1
@Agent_L โดยทั่วไปแล้วโลกจะถูกสร้างขึ้นทีละน้อยและแต่ละชิ้นมีตำแหน่ง X / Y เมื่อชิ้นส่วนอยู่ด้านหลังของผู้เล่นโดยพอ (เช่นหน้าจอ) มันจะถูกลบและพวกเขาจะสร้างจำนวนล่วงหน้าเท่านั้นดังนั้นพวกเขาจึงมักจะอยู่ในช่วงที่ค่อนข้างเล็ก - เกมหนึ่งที่ฉันทำไม่เคยมีพิกัดมากขึ้น น้อยกว่า ~ 1,000 หรือน้อยกว่า 0 แม้จะเป็นนักวิ่งที่ไม่มีที่สิ้นสุดสร้างแบบสุ่มเพราะอย่างนั้น - ฉันคอยติดตามตำแหน่งของผู้เล่นในแต่ละอันและดัชนีของแต่ละอันตามลำดับ
Nic Hartley

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

2
ที่ 1,000 พิกเซลต่อวินาทีมันจะใช้เวลามากกว่า 586 ล้านปีในการเป็นจำนวนเต็ม 64 บิต นี่เป็นปัญหาจริงๆถ้าคุณใช้ชนิดเล็ก ๆ เช่นจำนวนเต็ม 16 บิต
Lyndon White

38

การสร้างคำตอบของ XenoRoแทนที่จะเป็นวิธีการรูทใหม่ที่อธิบายไว้เราสามารถทำได้ดังนี้

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

player.position = (player.position + player.velocity) % worldBuffer.width;

นี่เป็นตัวอย่างของสิ่งที่ฉันพูดถึง:

ป้อนคำอธิบายรูปภาพที่นี่

นี่คือตัวอย่างของสิ่งที่เกิดขึ้นในตอนท้าย

ป้อนคำอธิบายรูปภาพที่นี่

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

โปรดทราบว่าคุณจะเริ่มต้นที่จะได้รับการทำซ้ำผลกับการใด ๆ PRNG และจำนวนสูงสุดของลำดับที่ไม่ซ้ำของคนรุ่น PRNG เป็นปกติจะน้อยกว่าความยาวของธาร (ที่ 2 จำนวนบิตที่ใช้ภายใน) กับmerzenne Twisterนี้ไม่ได้ มากของปัญหาในขณะที่มันใช้ 2.5K ของรัฐภายใน แต่ถ้าคุณใช้แตกต่างเล็ก ๆ คุณมี 2 ^ 127-1 ซ้ำสูงสุดก่อนที่จะทำซ้ำ (หรือแย่ลง) นี้เป็นยังคงเป็นจำนวนมากอย่างไรก็ตามทางดาราศาสตร์ คุณสามารถแก้ไขปัญหาช่วงเวลาการทำซ้ำได้แม้ว่า PRNG ของคุณจะมีช่วงเวลาสั้น ๆ ผ่านฟังก์ชั่นการผสมหิมะถล่มที่ดีสำหรับเมล็ดพันธุ์


ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
Josh

15

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

Spawner วางวัตถุบนหน้าจอด้วยความเร็วคงที่ในVector2.leftทิศทางที่กำหนด


3
ใช้งานได้กับ FlappyBird เพราะเป็นเกมที่ง่ายมาก ตามที่กล่าวไว้ในคำตอบของฉันเทคนิคเดียวกันในขณะที่ยังคงเป็นไปได้จะเป็นปัญหามากในสิ่งที่ซับซ้อนมากขึ้น (มีวัตถุ / รายละเอียดโลกมากขึ้น) เช่น Subway Surfer
XenoRo

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