我的相機上有 2 個腳本,一個用于跟隨玩家 (FollowTarget.cs),另一個用于隨著時間的推移在玩家死亡時 Slerp 相機的變換位置和旋轉 (DeathCam.cs)。
使用 DeathCam.cs,我試圖在死亡時隨著時間的推移順利地移動到 [desired/set in inspector] 位置和旋轉值,但目前相機直接跳到檢查器中設定的位置和旋轉。我認為這可能歸結為 transform.position = camPos; 在更新。
我試圖在 PlayDeathCam() 函式中設定位置和旋轉,但無法正常作業,目前已被注釋掉并替換為一個布林值,該布林值檢查更新以查看死亡凸輪是否處于活動狀態
代碼: FollowTarget.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FollowTarget : MonoBehaviour{
[Header("----- Target To Follow --------------------------------------------------")]
public GameObject target;
[Header("----- Adjustments To Make ------------------------------------------")]
public Vector3 adjustVal;
void Update(){
pos = new Vector3( target.transform.position.x adjustVal.x,
target.transform.position.y adjustVal.y,
target.transform.position.z adjustVal.z);
transform.position = pos;
}
}
代碼: DeathCam.cs
?using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DeathCam : MonoBehaviour{
[Header("----- Duration -----------------------------------------------------")]
[SerializeField] float duration = 5.0f;
[Header("----- Positions ----------------------------------------------------")]
[SerializeField] float finalPosX;
[SerializeField] float finalPosY;
[SerializeField] float finalPosZ;
[Header("----- Angles -------------------------------------------------------")]
[SerializeField] float tiltAngleX;
[SerializeField] float tiltAngleY;
[SerializeField] float tiltAngleZ;
[Header("--------------------------------------------------------------------")]
[SerializeField] Vector3 camPos;
[SerializeField] Quaternion camRot;
[SerializeField] bool deathCamActive;
///[ Start]
void Start(){
}
///[ Update]
void Update(){
if (deathCamActive) {
camPos = new Vector3((transform.position.x finalPosX),
(transform.position.y finalPosY),
(transform.position.z finalPosZ));
transform.position = camPos;
}
}
///[ PlayDeathCam]
public void PlayDeathCam(){
float tiltAroundX = camPos.x * tiltAngleX;
float tiltAroundY = camPos.y * tiltAngleY;
float tiltAroundZ = camPos.z * tiltAngleZ;
// camPos = new Vector3((transform.position.x finalPosX),
// (transform.position.y finalPosY),
// (transform.position.z finalPosZ));
camRot = Quaternion.Euler(tiltAroundX, tiltAroundY, tiltAroundZ);
transform.position = Vector3.Slerp(transform.position, camPos, Time.deltaTime * duration);
deathCamActive = true;
transform.rotation = Quaternion.Slerp(transform.rotation, camRot, Time.deltaTime * duration);
StartCoroutine("DeathCamSlow");
}
///[ DeathCamSlow]
IEnumerator DeathCamSlow(){
Time.timeScale = 0.3f;
yield return new WaitForSeconds(1.6f);
Time.timeScale = 1.0f;
}
}
uj5u.com熱心網友回復:
您的代碼有一些問題,應該可以修復,但首先讓我們嘗試反匯編一些似乎正在發生的混亂。
對于初學者來說,用 slerp 插值位置看起來是錯誤的。
但是您似乎已將您認為會在只會被呼叫一次的方法中執行影片的代碼。
我喜歡使用類似于以下的模式來分離我對觸發影片的思考
void StartAnimation()
{
StartCorouting(LerpDriverRoutine());
}
IEnumerator LerpDriverRoutine()
{
float x=0;
while (x<1)
{
ApplyLerp(x);
x =Time.deltaTime*speed;
yield return null;
}
ApplyLerp(1);
}
void ApplyLerp(float lerpAmount) // this will get called with varying amount as time passes
{
// use lerp amount here
}
雖然 lerping x=lerp(x,other,Time.deltaTime) 有時有意義,但更多時候卻沒有。在這里,您不是在值 A 和 B 之間徘徊,而是在當前值和目標之間徘徊,這會導致類似的結果,但通常不會感覺平滑。如果您想溫和地調整到目標值,通常使用 Mathf.SmoothDamp 會好得多。但是如果線性插值是你想要的,并且學習編碼影片你可能想從它開始,你需要將你的開始位置存盤在某個地方并將它用于 lerp(影片運行的時間),而不僅僅是使用當前價值,至少在你知道自己在做什么之前不會
IEnumerator LerpDriverRoutine()
{
float x=0;
Vector3 startPosition=transform.position;
Quaternion startRotation=transform.rotation;
while (x<1)
{
transform.position=Vector3.Lerp(startPosition,camPos,x);
transform.rotation=Quaternion.Slerp(startRotation,camRot,x);
x =Time.deltaTime*speed;
yield return null;
}
}
根據要求進行編輯:這是一個使用 smoothdamp 的示例。它有幾個優點:它總是緩慢地開始和結束,正好在中途達到峰值速度,并在接近目標時開始減速。您無需提前知道影片需要多長時間才能適應新狀態。您還可以在影片進行時更改目標值,只要您不丟失速度值,就不會出現任何明顯的抖動。SmoothDamp 使用一個外部輔助值來保存當前速度(缺點是您需要檢查移動時所需的誤差是否會收斂到目標值但實際??上可能無法達到)當行進距離較長時,影片將也需要更長的時間,但它會保留由 smoothTime 引數表示的一般動態。請注意,smoothTime 大致相當于影片中途而不是一路所用的時間,因為它永遠不會完全走完。默認值 0.75 意味著(非常粗略地)運動大約需要 1.5 秒才能達到所需值。
IEnumerator SmoothDampMovement(Vector3 target, float smoothTime=0.75f, float epsilon=0.01f)
{
float velocityX=0;
float velocityY=0;
float velocityZ=0;
var position=transform.position;
while (transform.position-target).Vector3.sqrMagnitude >epsilon)
{
position.x = Mathf.SmoothDamp(position.x, target.x, ref velocityX, smoothTime);
position.y = Mathf.SmoothDamp(position.y, target.y, ref velocityY, smoothTime);
position.z = Mathf.SmoothDamp(position.z, target.z, ref velocityZ, smoothTime));
transform.position=position;
yield return null;
}
}
對于旋轉,有 Mathf.SmoothDampAngle 可以處理 360 度回傳 0 的邊緣情況,我相信您可以根據上面的示例計算出詳細資訊
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/471738.html