查看我之前的回答的評論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行。
謝謝!儘管我現在從測試中看到了一個問題。旋轉開始後,其他滑動功能不再起作用。所以如果我刷到一邊然後旋轉,我不能再刷卡。這似乎很奇怪,我希望這是一個快速修復。另外,有沒有辦法讓它向內旋轉? Atm隨相機朝外旋轉。謝謝:) – Natecurt3030
好像在重新啓動和第二次測試後滑動工作,所以也許這只是一個奇怪的錯誤。不過,我仍然希望任何人有可能讓相機朝內旋轉! – Natecurt3030
所以我認爲你所追求的是讓相機圍繞相機外部的一個點旋轉,而不是圍繞相機的一個本地軸。這是一項非常難完成的任務,因爲您必須首先在相機應旋轉的世界空間中指定一個參考點。這可能是固定的,例如,相機前面有20個單位,或者您可能想要選擇自定義點/對象來旋轉。不知道你在追求什麼,我真的幫不了什麼忙。對於那個很抱歉。 – LWKatze