ดูคำตอบนี้ด้วย
มีวิธีการทั่วไปสองวิธีในการใช้Lerp
:
1. การผสมเชิงเส้นระหว่างจุดเริ่มต้นและจุดสิ้นสุด
progress = Mathf.Clamp01(progress + speedPerTick);
current = Mathf.Lerp(start, end, progress);
นี่เป็นรุ่นที่คุณคุ้นเคยมากที่สุด
2. ความง่ายในการอธิบายต่อเป้าหมาย
current = Mathf.Lerp(current, target, sharpnessPerTick);
โปรดทราบว่าในรุ่นนี้current
ค่าจะปรากฏเป็นทั้งเอาต์พุตและอินพุต มันแทนที่start
ตัวแปรดังนั้นเราจึงเริ่มต้นจากทุกที่ที่เราย้ายไปยังการปรับปรุงล่าสุด นี่คือสิ่งที่ให้Lerp
หน่วยความจำรุ่นนี้จากเฟรมหนึ่งไปอีกเฟรมหนึ่ง จากนี้ย้ายจุดเริ่มต้นเราแล้วจากนั้นย้ายส่วนของระยะทางที่ไปทางtarget
dictated โดยsharpness
พารามิเตอร์
พารามิเตอร์นี้ไม่มาก "ความเร็ว" อีกต่อไปเพราะเราเข้าใกล้เป้าหมายในนักปราชญ์เหมือนแฟชั่น ถ้าsharpnessPerTick
เป็น0.5
เช่นนั้นในการอัปเดตครั้งแรกเราจะย้ายไปครึ่งทางเพื่อบรรลุเป้าหมายของเรา จากนั้นในการอัพเดทครั้งต่อไปเราจะเลื่อนระยะทางที่เหลืออีกครึ่งหนึ่ง (ดังนั้นหนึ่งในสี่ของระยะทางเริ่มต้นของเรา) จากนั้นเราก็จะย้ายอีกครึ่งหนึ่ง ...
สิ่งนี้จะช่วยให้ "ความง่ายในการอธิบาย" ซึ่งการเคลื่อนที่นั้นรวดเร็วเมื่ออยู่ห่างจากเป้าหมายและค่อยๆช้าลงเมื่อเข้าใกล้ asymptotically (แม้ว่าจะมีจำนวนความแม่นยำที่ไม่มีที่สิ้นสุด เข้าใกล้พอ) มันยอดเยี่ยมสำหรับการไล่ล่าค่าเป้าหมายที่เคลื่อนไหวหรือการป้อนข้อมูลที่มีเสียงรบกวนให้เรียบโดยใช้ " ค่าเฉลี่ยเคลื่อนที่แบบเอ็กซ์โปเนนเชียล" โดยปกติจะใช้sharpnessPerTick
พารามิเตอร์ขนาดเล็กมากเช่น0.1
หรือเล็กกว่า
แต่คุณพูดถูกมีข้อผิดพลาดในลิงค์ upvote ที่คุณตอบ มันไม่ถูกต้องสำหรับdeltaTime
วิธีที่ถูกต้อง นี่เป็นข้อผิดพลาดทั่วไปมากเมื่อใช้รูปแบบLerp
นี้
รูปแบบแรกของLerp
คือเชิงเส้นดังนั้นเราจึงสามารถปรับความเร็วเชิงเส้นได้โดยการคูณด้วยdeltaTime
:
progress = Mathf.Clamp01(progress + speedPerSecond * Time.deltaTime);
// or progress = Mathf.Clamp01(progress + Time.deltaTime / durationSeconds);
current = Mathf.Lerp(start, end, progress);
แต่การผ่อนคลายแบบเอ็กซ์โปเนนเชียลของเราไม่ใช่แบบเชิงเส้นดังนั้นเพียงแค่คูณsharpness
พารามิเตอร์ของเราด้วยdeltaTime
จะไม่ทำให้การแก้ไขเวลาถูกต้อง สิ่งนี้จะปรากฏเป็นผู้ตัดสินในการเคลื่อนไหวหากอัตราเฟรมของเราผันผวนหรือการเปลี่ยนแปลงของความคมชัดที่ผ่อนคลายหากคุณเปลี่ยนจาก 30 เป็น 60 อย่างสม่ำเสมอ
แต่เราจำเป็นต้องใช้การแก้ไขเลขชี้กำลังสำหรับความง่ายในการอธิบายของเรา:
blend = 1f - Mathf.Pow(1f - sharpness, Time.deltaTime * referenceFramerate);
current = Mathf.Lerp(current, target, blend);
นี่referenceFramerate
เป็นเพียงค่าคงที่ที่ต้องการ30
เก็บหน่วยให้sharpness
เหมือนกับที่เราใช้ก่อนที่จะแก้ไขเวลา
มีข้อผิดพลาดที่พิสูจน์ได้อีกข้อหนึ่งในรหัสนั้นซึ่งใช้Slerp
- การแก้ไขเชิงเส้นทรงกลมมีประโยชน์เมื่อเราต้องการอัตราการหมุนที่สอดคล้องกันตลอดการเคลื่อนไหวทั้งหมด แต่ถ้าเราจะใช้การแจกแจงแบบไม่เป็นเชิงเส้นตรงนั้นLerp
จะให้ผลที่ไม่สามารถแยกแยะได้และมันก็ถูกกว่า ;) Quaternions lerp ดีกว่าเมทริกซ์ทำดังนั้นนี่จึงเป็นการทดแทนที่ปลอดภัย