2017-08-20 50 views
1

我有一臺相機朝向地面,我想平移遠處的目標物體。Unity相機Quaternion.RotateTowards無滾動/銀行

目前,我有以下實現這一點:

Vector3 dir = targetPoint - transform.position; 
Quaternion lookRotation = Quaternion.LookRotation(dir); 
Quaternion newRotation = Quaternion.RotateTowards(transform.rotation, lookRotation, rotationDamping * Time.deltaTime); 
transform.rotation = newRotation; 

相機進行轉動,並最終在目標對象的正確指向,但由於照相機平底鍋它向一側傾斜使我的遊戲世界設定一個角度給觀衆,這是非常令人迷惑:

Camera rotation example 1

我怎麼能限制攝像機的角度某種方式讓天邊總是平坦的相機?

謝謝!下面

更新

添加由@Isaac建議的生產線生產相對於地平線正確的旋轉,但在它仍然不是我要找的開始突然捕捉到Z = 0 。

transform.localEulerAngles = new Vector3 (transform.localEulerAngles.x, transform.localEulerAngles.y, 0); 

Camera rotation example 2

回答

1

在這個問題上有一個很好的Q/A on gamedev.stackexchange。你應該嘗試在那裏建議的俯仰/偏航系統。
另一個建議是在旋轉過程中糾正相機晃動。

public float rollCorrectionSpeed; 
public void Update() 
{ 
    float roll = Vector3.Dot(transform.right, Vector3.up); 
    transform.Rotate(0, 0, -roll * rollCorrectionSpeed); 

    Vector3 dir = targetPoint.position - transform.position; 
    Quaternion lookRotation = Quaternion.LookRotation(dir); 
    Quaternion newRotation = Quaternion.RotateTowards(transform.rotation, lookRotation, rotationDamping * Time.deltaTime); 
    transform.rotation = newRotation; 
} 

編輯:
有一個簡單的解決方案:只要讓你從0

public void Update() 
{ 
    Vector3 angles = transform.rotation.eulerAngles; 
    Quaternion from = Quaternion.Euler(angles.x, angles.y, 0); 

    Vector3 dir = targetPoint.position - transform.position;   
    Quaternion to = Quaternion.LookRotation(dir); 

    transform.rotation = Quaternion.RotateTowards(from, to, rotationDamping * Time.deltaTime); 
} 
+0

我也試驗過你的第二種技術,你仍然會得到初始跳躍,而不是朝着z軸平滑旋轉。我還編輯了'targetPoint.position'只是'targetPoint',因爲這就是我認爲你的意思。 – Isaac

+0

你的第一個解決方案解決了它!實際上,我只是將rollCorrectionSpeed設置爲1,它完美地工作。非常感謝,也可以鏈接到我認爲非常有趣的gamedev討論。 – bbeckford

1

在實驗中,我發現2個可能的解決方案取決於你想要什麼。

如果你只是想跟隨目標,我會建議使用LookAt,它會自動對齊世界。在你的代碼中(更新)transform.LookAt(dir);

如果您需要/想要在平移效果更新後設置localEulerAngles旋轉。這是我做的這工作:

//this is your code 
    Vector3 dir = targetPoint - transform.position; 
    Quaternion lookRotation = Quaternion.LookRotation(dir); 
    Quaternion newRotation = Quaternion.RotateTowards(transform.rotation, lookRotation, rotationDamping * Time.deltaTime); 
    transform.rotation = newRotation; 

//this is what I added 
    transform.localEulerAngles = new Vector3 (transform.localEulerAngles.x, transform.localEulerAngles.y, 0); 

加入簡單地取相機使用四元數更新旋轉後面臨的方式設置的Z旋轉至零。

讓我知道如果您有任何疑問:)

//////////////////////////////// ////////////////////////////////////////////////// ////////////////////////////////////////////////// /////////

新的信息/編輯:

我相信我已經找到了解決方案,但它是醜陋,我將不勝感激反饋,是否口吃等

這段代碼基本上和以前一樣,但現在它檢查看z角度並使用一個我稱爲zDamping的變量手動編輯它,該變量影響相機僅圍繞z訪問旋轉的速度。

我加了更新之外:

public float zDamping; //public only for testing, it's convenient for finding an optimal value 
private bool rotationCheck = false; 

然後裏面update()

//This is your code (unchanged) 
     Vector3 targetPoint = target.transform.position; 
     Vector3 dir = targetPoint - transform.position; 
     Quaternion lookRotation = Quaternion.LookRotation (dir); 
     Quaternion newRotation = Quaternion.RotateTowards (transform.rotation, lookRotation, rotationDamping * Time.deltaTime); 

//This is what is new (remove my addition from before edits or it won't work) 
     if (transform.localEulerAngles.z >= 180f && transform.localEulerAngles.z <= 359f && !rotationCheck) { 
      transform.localEulerAngles = new Vector3 (transform.localEulerAngles.x, transform.localEulerAngles.y, transform.localEulerAngles.z + (rotationDamping * zDamping)); 
      transform.rotation = newRotation; 
     } 
     else if (transform.localEulerAngles.z <= -180f && transform.localEulerAngles.z >= 1f && !rotationCheck) { 
      transform.localEulerAngles = new Vector3 (transform.localEulerAngles.x, transform.localEulerAngles.y, transform.localEulerAngles.z - (rotationDamping * zDamping)); 
      transform.rotation = newRotation; 
     } 
     else { 
      transform.rotation = newRotation; 
      transform.localEulerAngles = new Vector3 (transform.localEulerAngles.x, transform.localEulerAngles.y, 0); 
      rotationCheck = true; 
     } 

正如我所說的,這個解決方案是很醜陋,但它可能工作。你必須看看zDamping值的工作原理是什麼,看起來很自然(我建議以.01開頭)。一旦你接近該值,也會有一個小小的「跳躍」,但是越接近360°和1f就越小,跳躍越小。過小的危險是過沖,但即使過沖也應該起作用,但這需要很短的時間。

測試一下,讓我知道你在想什麼,對不起,我現在找不到更優雅的東西。我還嘗試添加一個單獨的Quaternion來專門旋轉z軸,但它不起作用;隨時嘗試一下,如果你想,我可以給我更多的細節,我做了什麼。

祝你好運,再次抱歉,馬虎的解決方案。

+0

嗨@Isaac,感謝您的幫助。我需要一個平穩的旋轉,因此使用Quaternion.RotateTowards,我嘗試添加你的線,並且它現在保持與地平線一致,一開始它向z = 0搖晃。任何想法如何解決這個問題? http://i.imgur.com/WXqiIln.gif – bbeckford

+0

感謝您的所有幫助@Isaac,冥王星的答案最終成爲我最簡單,最正確的答案。如果我可以給你一些我會的賞金! – bbeckford

+1

np,祝你好運! – Isaac

0

添加代碼在你行旋轉四元數的z旋轉,希望它會解決這個問題。

Vector3 dir = targetPoint - transform.position; 
Quaternion lookRotation = Quaternion.LookRotation(dir); 
Quaternion newRotation = Quaternion.RotateTowards(transform.rotation, lookRotation, rotationDamping * Time.deltaTime); 
newRotation.eulerAngles = new Vector3(newRotation.eulerAngles.x,newRotation.eulerAngles.y,transform.rotation.eulerAngles.z); 
transform.rotation = newRotation; 
+0

這實際上並不朝向零旋轉,它只是維持當前的z旋轉。例如,如果您以-10的z旋轉開始,它將保持在-10而不是旋轉到零。 – Isaac

+0

葉普,這就是我認爲@bbeckford需要的 – ZayedUpal