คุณต้องการแยกการอัปเดต (ติ๊กตรรกะ) และอัตราการวาด (เห็บแสดงผล)
การอัปเดตของคุณจะสร้างตำแหน่งของวัตถุทั้งหมดในโลกที่จะวาด
ฉันจะครอบคลุมความเป็นไปได้ที่แตกต่างกันสองแบบที่นี่สิ่งที่คุณร้องขอการคาดการณ์และวิธีอื่นการแก้ไข
1
การคาดการณ์คือที่ที่เราจะคำนวณตำแหน่ง (ทำนาย) ของวัตถุที่เฟรมถัดไปแล้วสอดแทรกระหว่างตำแหน่งวัตถุปัจจุบันและตำแหน่งที่วัตถุจะอยู่ที่เฟรมถัดไป
การทำเช่นนี้วัตถุที่จะวาดแต่ละคนจะต้องมีการเชื่อมโยงและvelocity
position
ในการค้นหาตำแหน่งที่วัตถุจะอยู่ในเฟรมถัดไปเราเพียงเพิ่มvelocity * draw_timestep
ตำแหน่งปัจจุบันของวัตถุเพื่อค้นหาตำแหน่งที่คาดการณ์ของเฟรมถัดไป draw_timestep
คือระยะเวลาที่ผ่านไปตั้งแต่การทำเครื่องหมายการเรนเดอร์ก่อนหน้า (aka การเรียกการดึงก่อนหน้า)
หากคุณปล่อยไว้ที่นี่คุณจะพบว่าวัตถุ "สั่นไหว" เมื่อตำแหน่งที่คาดการณ์ของพวกเขาไม่ตรงกับตำแหน่งจริงที่เฟรมถัดไป ในการลบการกะพริบคุณสามารถจัดเก็บตำแหน่งที่คาดการณ์และlerpระหว่างตำแหน่งที่คาดการณ์ไว้ก่อนหน้านี้และตำแหน่งที่คาดการณ์ใหม่ในแต่ละขั้นตอนการวาดโดยใช้เวลาที่ผ่านไปนับตั้งแต่การอัพเดทก่อนหน้านี้เป็นปัจจัย lerp สิ่งนี้จะทำให้เกิดพฤติกรรมที่ไม่ดีเมื่อวัตถุที่เคลื่อนไหวเร็วเปลี่ยนตำแหน่งทันทีและคุณอาจต้องการจัดการกับกรณีพิเศษ ทุกอย่างที่กล่าวในย่อหน้านี้เป็นสาเหตุที่คุณไม่ต้องการใช้การคาดการณ์
2
การแก้ไขคือที่ที่เราเก็บสถานะของการอัพเดตสองครั้งล่าสุดและการสอดแทรกระหว่างการอัปเดตนั้นขึ้นอยู่กับจำนวนเวลาปัจจุบันที่ผ่านไปตั้งแต่การอัพเดตก่อนหน้านี้ ในการติดตั้งนี้แต่ละวัตถุต้องมีการเชื่อมโยงและposition
previous_position
ในกรณีนี้รูปวาดของเราจะเป็นตัวแทนของหนึ่งขีดการอัปเดตที่เลวร้ายที่สุดที่อยู่เบื้องหลังเกมปัจจุบันและที่ดีที่สุดในสถานะเดียวกันกับเห็บอัปเดตปัจจุบัน
ในความคิดของฉันคุณอาจต้องการการแก้ไขตามที่ฉันได้อธิบายเนื่องจากเป็นเรื่องง่ายกว่าที่ทั้งสองจะนำไปใช้และการวาดเศษเสี้ยวของวินาที (เช่น 1/60 วินาที) ที่อยู่หลังสถานะอัปเดตปัจจุบันของคุณนั้นดี
แก้ไข:
ในกรณีข้างต้นไม่เพียงพอที่จะให้คุณสามารถใช้งานได้นี่เป็นตัวอย่างของวิธีการแก้ไขที่ฉันได้อธิบายไว้ ฉันจะไม่ครอบคลุมการคาดการณ์เพราะฉันไม่สามารถนึกถึงสถานการณ์ในโลกแห่งความเป็นจริงที่คุณควรจะชอบ
เมื่อคุณสร้างวัตถุที่วาดได้มันจะเก็บคุณสมบัติที่จำเป็นในการวาด (เช่นข้อมูลสถานะที่จำเป็นในการวาด)
สำหรับตัวอย่างนี้เราจะเก็บตำแหน่งและการหมุน คุณอาจต้องการเก็บคุณสมบัติอื่น ๆ เช่นสีหรือตำแหน่งพิกัดพื้นผิว (เช่นถ้าเลื่อนพื้นผิว)
เพื่อป้องกันไม่ให้ข้อมูลถูกแก้ไขขณะที่เธรดการเรนเดอร์กำลังทำการวาด (เช่นตำแหน่งของวัตถุหนึ่งถูกเปลี่ยนแปลงในขณะที่การเรนเดอร์ดึงออก แต่ส่วนอื่น ๆ ทั้งหมดยังไม่ได้รับการอัพเดต) เราจำเป็นต้องใช้การบัฟเฟอร์คู่บางประเภท
previous_state
วัตถุที่เก็บสำเนาที่สองของมัน ผมจะใส่ไว้ในอาร์เรย์และการอ้างอิงถึงพวกเขาเป็นและprevious_state[0]
previous_state[1]
ต้องการสำเนาสองชุดในทำนองเดียวกันcurrent_state
ต้องการสองสำเนาของมัน
เพื่อติดตามว่ามีการใช้สำเนาของ double buffer ใดเราจัดเก็บตัวแปรstate_index
ซึ่งมีให้สำหรับทั้งการอัพเดตและการดึงเธรด
เธรดการอัพเดทจะคำนวณคุณสมบัติทั้งหมดของวัตถุโดยใช้ข้อมูลของตัวเอง (โครงสร้างข้อมูลใด ๆ ที่คุณต้องการ) จากนั้นมันจะคัดลอกcurrent_state[state_index]
ไปprevious_state[state_index]
และสำเนาข้อมูลใหม่ที่เกี่ยวข้องกับการวาดภาพposition
และการเข้าสู่rotation
current_state[state_index]
จากนั้นก็state_index = 1 - state_index
เพื่อพลิกสำเนาที่ใช้ในปัจจุบันของบัฟเฟอร์คู่
ทุกอย่างในย่อหน้าข้างต้นจะต้องทำโดยใช้ล็อคเอาออก current_state
ทุกอย่างในย่อหน้าข้างต้นจะต้องมีการกระทำที่มีการล็อคที่ถ่ายออกมาในการอัพเดตและดึงเธรดจะนำการล็อกนี้ออก การล็อคจะดำเนินการในช่วงระยะเวลาของการคัดลอกข้อมูลสถานะซึ่งรวดเร็ว
ในเธรดการเรนเดอร์จากนั้นคุณทำการแก้ไขเชิงเส้นกับตำแหน่งและการหมุนดังนี้:
current_position = Lerp(previous_state[state_index].position, current_state[state_index].position, elapsed/update_tick_length)
ที่ไหน elapsed
เป็นระยะเวลาที่ได้ผ่านในเธรด render เนื่องจากเห็บปรับปรุงล่าสุดและupdate_tick_length
เป็นระยะเวลาที่อัตราการปรับปรุงการแก้ไขของคุณใช้เวลาต่อเห็บ (เช่นที่ 20fps ปรับปรุงupdate_tick_length = 0.05
)
หากคุณไม่ทราบว่าLerp
ฟังก์ชั่นข้างต้นเป็นแล้วบทความวิกิพีเดียเช็คเอาท์ในเรื่อง: เชิงเส้นการแก้ไข อย่างไรก็ตามหากคุณไม่ทราบว่า lerping คืออะไรคุณอาจยังไม่พร้อมที่จะใช้การปรับปรุง / วาดแบบแยกส่วนด้วยการวาดการแก้ไข