2016-07-19 72 views
3

我在這裏有一些CS代碼,我試圖在統一使用繞y軸旋轉相機。問題是相機目前似乎圍繞z軸旋轉,這在我的遊戲中造成了一些視覺上的困難。在Unity3D C#中的相機旋轉問題(可能很容易修復)

public class TouchCamera : MonoBehaviour { 
Vector2?[] oldTouchPositions = { 
    null, 
    null 
}; 
Vector2 oldTouchVector; 
float oldTouchDistance; 

void Update() { 
    if (Input.touchCount == 0) { 
     oldTouchPositions[0] = null; 
     oldTouchPositions[1] = null; 
    } 
    else if (Input.touchCount == 1) { 
     if (oldTouchPositions[0] == null || oldTouchPositions[1] != null) { 
      oldTouchPositions[0] = Input.GetTouch(0).position; 
      oldTouchPositions[1] = null; 
     } 
     else { 
      Vector2 newTouchPosition = Input.GetTouch(0).position; 

      transform.position += transform.TransformDirection((Vector3)((oldTouchPositions[0] - newTouchPosition) * GetComponent<Camera>().orthographicSize/GetComponent<Camera>().pixelHeight * 2f)); 

      oldTouchPositions[0] = newTouchPosition; 
     } 
    } 
    else { 
     if (oldTouchPositions[1] == null) { 
      oldTouchPositions[0] = Input.GetTouch(0).position; 
      oldTouchPositions[1] = Input.GetTouch(1).position; 
      oldTouchVector = (Vector2)(oldTouchPositions[0] - oldTouchPositions[1]); 
      oldTouchDistance = oldTouchVector.magnitude; 
     } 
     else { 
      Vector2 screen = new Vector2(GetComponent<Camera>().pixelWidth, GetComponent<Camera>().pixelHeight); 

      Vector2[] newTouchPositions = { 
       Input.GetTouch(0).position, 
       Input.GetTouch(1).position 
      }; 
      Vector2 newTouchVector = newTouchPositions[0] - newTouchPositions[1]; 
      float newTouchDistance = newTouchVector.magnitude; 

      transform.position += transform.TransformDirection((Vector3)((oldTouchPositions[0] + oldTouchPositions[1] - screen) * GetComponent<Camera>().orthographicSize/screen.y)); 
      transform.localRotation *= Quaternion.Euler(new Vector3(0, 0, Mathf.Asin(Mathf.Clamp((oldTouchVector.y * newTouchVector.x - oldTouchVector.x * newTouchVector.y)/oldTouchDistance/newTouchDistance, -1f, 1f))/0.0174532924f)); 
      GetComponent<Camera>().orthographicSize *= oldTouchDistance/newTouchDistance; 
      transform.position -= transform.TransformDirection((newTouchPositions[0] + newTouchPositions[1] - screen) * GetComponent<Camera>().orthographicSize/screen.y); 

      oldTouchPositions[0] = newTouchPositions[0]; 
      oldTouchPositions[1] = newTouchPositions[1]; 
      oldTouchVector = newTouchVector; 
      oldTouchDistance = newTouchDistance; 
     } 
    } 
} 

我是藝術家,絕不是編碼員,這段代碼不是我的創作。我只是尋求幫助來糾正它,以適應我的需求。所以如果有人能讓我知道我可以對這個當前代碼做出的最簡單的調整,我會非常感激。我知道這不是最常見的問題,我只是希望得到一點幫助。

回答

1

你是對的 - 這是一個非常簡單的解決方案。所有你需要做的改變旋轉軸捏捏以下行(約49行):

transform.localRotation *= Quaternion.Euler(new Vector3(0, 0, Mathf.Asin(Mathf.Clamp((oldTouchVector.y * newTouchVector.x - oldTouchVector.x * newTouchVector.y)/oldTouchDistance/newTouchDistance, -1f, 1f))/0.0174532924f)); 

你會發現,開始

new Vector3 

其中有三個參數的一部分,

new Vector3(x value, y value, z value) 

眼下,的Vector3設置爲

new Vector3(x value = 0, y value = 0, z value = rotation data) 

要旋轉相機圍繞其Y軸,換行此

transform.localRotation *= Quaternion.Euler(new Vector3(0, Mathf.Asin(Mathf.Clamp((oldTouchVector.y * newTouchVector.x - oldTouchVector.x * newTouchVector.y)/oldTouchDistance/newTouchDistance, -1f, 1f))/0.0174532924f, 0)); 

我所做的只是掉在新的Vector3的Y和Z值的當前設置。希望這可以幫助!

+0

謝謝!儘管我現在從測試中看到了一個問題。旋轉開始後,其他滑動功能不再起作用。所以如果我刷到一邊然後旋轉,我不能再刷卡。這似乎很奇怪,我希望這是一個快速修復。另外,有沒有辦法讓它向內旋轉? Atm隨相機朝外旋轉。謝謝:) – Natecurt3030

+0

好像在重新啓動和第二次測試後滑動工作,所以也許這只是一個奇怪的錯誤。不過,我仍然希望任何人有可能讓相機朝內旋轉! – Natecurt3030

+0

所以我認爲你所追求的是讓相機圍繞相機外部​​的一個點旋轉,而不是圍繞相機的一個本地軸。這是一項非常難完成的任務,因爲您必須首先在相機應旋轉的世界空間中指定一個參考點。這可能是固定的,例如,相機前面有20個單位,或者您可能想要選擇自定義點/對象來旋轉。不知道你在追求什麼,我真的幫不了什麼忙。對於那個很抱歉。 – LWKatze

0

查看我之前的回答的評論thread for context on this answer。

有兩種方法可讓您的相機繞着某個點進入軌道。在做其他事情之前,在Unity中創建一個空的GameObject並將其設置在希望相機繞行的固定點。確保GameObject在相機的視線內。然後將您的相機加入空GameObject。

對於簡單(但更嚴格)的方法,將TouchCamera腳本附加到Empty GameObject。從相機中取出TouchCamera腳本。現在在腳本中的Update方法開始之上添加這一行public Camera camera。在您的腳本中,將所有出現的GetComponent<Camera>()替換爲camera。保存你的腳本並返回到Unity。最後,單擊您的空GameObject並將您的相機拖到TouchCamera組件的Serialized Camera字段中。這種方法基本上將相機的控制權移動到空GameObject上。

對於更復雜(但更靈活)的方法,創建一個新的C#腳本並將其命名爲「CameraControl」。然後將以下代碼複製並粘貼到腳本中(替換已存在的任何代碼)。

using UnityEngine; 
using UnityEngine.UI; 
using System; 
using System.Collections; 

public class CameraControl : MonoBehaviour { 

Vector2?[] oldTouchPositions = { 
    null, 
    null 
}; 
Vector2 oldTouchVector; 
float oldTouchDistance; 

public Transform CenterOfRotation; 
public Camera camera; 

private Vector2 actualCenter; 
private Vector2 prevTouchDelta; 
private Vector3 prevMousePosition; 
private bool rotate; 

void Start() 
{ 
    //swap with below commented line for y rotation. 
    actualCenter = new Vector2(CenterOfRotation.position.x, CenterOfRotation.position.z); 
    //actualCenter = new Vector2(CenterOfRotation.position.x, CenterOfRotation.position.y); 
} 

void Update() { 
    if(!rotate){ 

     if (Input.touchCount == 0) { 
      oldTouchPositions[0] = null; 
      oldTouchPositions[1] = null; 
     } 
     else if (Input.touchCount == 1) { 
      if (oldTouchPositions[0] == null || oldTouchPositions[1] != null) { 
       oldTouchPositions[0] = Input.GetTouch(0).position; 
       oldTouchPositions[1] = null; 
      } 
      else { 
       Vector2 newTouchPosition = Input.GetTouch(0).position; 

       transform.position += transform.TransformDirection((Vector3)((oldTouchPositions[0] - newTouchPosition) * camera.orthographicSize/camera.pixelHeight * 2f)); 

       oldTouchPositions[0] = newTouchPosition; 
      } 
     } 
     else { 
      if (oldTouchPositions[1] == null) { 
       oldTouchPositions[0] = Input.GetTouch(0).position; 
       oldTouchPositions[1] = Input.GetTouch(1).position; 
       oldTouchVector = (Vector2)(oldTouchPositions[0] - oldTouchPositions[1]); 
       oldTouchDistance = oldTouchVector.magnitude; 
      } 
      else { 
       Vector2 screen = new Vector2(camera.pixelWidth, camera.pixelHeight); 

       Vector2[] newTouchPositions = { 
        Input.GetTouch(0).position, 
        Input.GetTouch(1).position 
       }; 
       Vector2 newTouchVector = newTouchPositions[0] - newTouchPositions[1]; 
       float newTouchDistance = newTouchVector.magnitude; 


       transform.position += transform.TransformDirection((Vector3)((oldTouchPositions[0] + oldTouchPositions[1] - screen) * camera.orthographicSize/screen.y)); 
       //transform.localRotation *= Quaternion.Euler(new Vector3(0, Mathf.Asin(Mathf.Clamp((oldTouchVector.y * newTouchVector.x - oldTouchVector.x * newTouchVector.y)/oldTouchDistance/newTouchDistance, -1f, 1f))/0.0174532924f, 0)); 
       camera.orthographicSize *= oldTouchDistance/newTouchDistance; 
       transform.position -= transform.TransformDirection((newTouchPositions[0] + newTouchPositions[1] - screen) * camera.orthographicSize/screen.y); 

       oldTouchPositions[0] = newTouchPositions[0]; 
       oldTouchPositions[1] = newTouchPositions[1]; 
       oldTouchVector = newTouchVector; 
       oldTouchDistance = newTouchDistance; 
      } 
     } 
    } 
    else{ 
     InwardRotation(); 
    } 

} 

void OnGUI() 
{ 
    rotate = GUILayout.Toggle(rotate, "Toggle For Rotation", "Button"); 
} 

void InwardRotation() 
{ 
    //mouse version 
    if(Input.GetMouseButton(0)) 
    { 
     //distance from center of screen to touch 
     Vector3 centerScreen = camera.ViewportToScreenPoint(new Vector3(0.5f, 0.5f, 1)); 
     Vector3 mouseDelta = Input.mousePosition - new Vector3(centerScreen.x, centerScreen.y, 0f); 

     //if mouse doesn't move very much, don't rotate 
     if(mouseDelta.sqrMagnitude < 0.1f) 
      return; 

     //attempts to make movement smoother 
     if(prevMousePosition == Vector3.zero) 
      prevMousePosition = mouseDelta; 

     //this gets the angle between the current touch and the last touch 
     float theta = Mathf.Atan2(mouseDelta.y, mouseDelta.x) - Mathf.Atan2(prevMousePosition.y, prevMousePosition.x); 

     //Gets the rotated coordinates of the camera. Swap with below commented line for y rotation. 
     Vector2 newPos = RotatedCoordinates(transform.position.x, transform.position.z, theta, CenterOfRotation.position, true); 
     //Vector2 newPos = RotatedCoordinates(transform.position.x, transform.position.y, theta, CenterOfRotation.position, true); 
     Debug.Log("New Pos = " + newPos); 

     //swap with below commented line for y rotation. 
     transform.localPosition = new Vector3(newPos.x, transform.localPosition.y, newPos.y); 
     //transform.localPosition = new Vector3(newPos.x, newPos.y, transform.localPosition.z); 

     transform.LookAt(CenterOfRotation); 

     prevMousePosition = mouseDelta; 
    } 
    if(Input.touches.Length > 0f) 
    { 
     //distance from center of screen to touch 
     Vector3 centerScreen = camera.ViewportToScreenPoint(new Vector3(0.5f, 0.5f, 1)); 
     Vector2 touchDelta = Input.GetTouch(0).position - new Vector2(centerScreen.x, centerScreen.y); 

     //if mouse doesn't move very much, don't rotate 
     if(touchDelta.sqrMagnitude < 0.1f) 
      return; 

     //attempts to make movement smoother 
     if(prevTouchDelta == Vector2.zero) 
      prevTouchDelta = touchDelta; 

     //this gets the angle between the current touch and the last touch 
     float theta = Mathf.Atan2(touchDelta.y, touchDelta.x) - Mathf.Atan2(prevTouchDelta.y, prevTouchDelta.x); 

     //Gets the rotated coordinates of the camera. Swap with below commented line for y rotation. 
     Vector2 newPos = RotatedCoordinates(transform.position.x, transform.position.z, theta, CenterOfRotation.position, true); 
     //Vector2 newPos = RotatedCoordinates(transform.position.x, transform.position.y, theta, CenterOfRotation.position, true); 
     Debug.Log("New Pos = " + newPos); 

     //swap with below commented line for y rotation. 
     transform.localPosition = new Vector3(newPos.x, transform.localPosition.y, newPos.y); 
     //transform.localPosition = new Vector3(newPos.x, newPos.y, transform.localPosition.z); 

     transform.LookAt(CenterOfRotation); 

     prevTouchDelta = touchDelta; 
    } 

    else{ 
     prevTouchDelta = Vector2.zero; 
    } 
} 

/// <summary> 
/// This method returns the coordinates of a plane rotated about its origin. It translates a point from one place on a unit circle to another. 
/// </summary> 
/// <returns>The coordinates.</returns> 
/// <param name="x">The x coordinate.</param> 
/// <param name="y">The y coordinate.</param> 
/// <param name="theta">Theta.</param> 
/// <param name="ThetaInRad">If set to <c>true</c> theta in RAD.</param> 
public Vector2 RotatedCoordinates(float x, float y, float theta, Vector2 center, bool ThetaInRad = false) 
{ 
    if(!ThetaInRad) 
     theta *= Mathf.Deg2Rad; 

    Vector2 XY = new Vector2((Mathf.Cos(theta) * (x - center.x) - Mathf.Sin(theta) * (y - center.y)) + center.x, (Mathf.Sin(theta) * (x - center.x) + Mathf.Cos(theta) * (y - center.y)) + center.y); 
    return XY; 
} 

}

現在附加給你的相機(這應該是空的遊戲對象的孩子),然後卸下TouchCamera腳本。您會注意到CameraControl組件中有兩個字段,一個讀取「旋轉中心」和一個讀取「相機」。將空遊戲對象和相機分別拖到這些字段上。如果您跳過此步驟,此腳本將拋出空引用錯誤。現在只需點擊播放。當您單擊播放窗口左上角的Toggle For Rotation按鈕時,您可以通過拖動鼠標指針或單指圍繞屏幕中心來旋轉攝像頭。您可以從空GameObject中解開相機,並且腳本仍然可以工作。您還可以通過提供不同的變換在空間中的任何點進行軌道運動。通過一些編輯,您也可以完全消除變形,並在World Space中使用Vector3作爲參考點,但是您需要自己控制相機的實際旋轉,而不需要線條transform.LookAt(CenterOfRotation);。您可以通過編輯三條線來更改旋轉軸,位於大約30行,145行和151行。

+0

哇!認真地感謝幫助!感謝:D – Natecurt3030