คุณต้องการแยกการอัปเดต (ติ๊กตรรกะ) และอัตราการวาด (เห็บแสดงผล)
การอัปเดตของคุณจะสร้างตำแหน่งของวัตถุทั้งหมดในโลกที่จะวาด
ฉันจะครอบคลุมความเป็นไปได้ที่แตกต่างกันสองแบบที่นี่สิ่งที่คุณร้องขอการคาดการณ์และวิธีอื่นการแก้ไข
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 คืออะไรคุณอาจยังไม่พร้อมที่จะใช้การปรับปรุง / วาดแบบแยกส่วนด้วยการวาดการแก้ไข