2016-07-19 2 views
3

여기에 y 축을 중심으로 카메라를 회전시키기 위해 사용하려는 CS 코드가 있습니다. 문제는 현재 카메라가 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 행) 조정할 수 있습니다 : 당신은 세 가지 인수가

new Vector3 

시작 부분을 알 수 있습니다

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(x value, y value, z value) 

는 지금의 Vector3은

new Vector3(x value = 0, y value = 0, z value = rotation data) 
,536,913,632로 설정 10

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)); 

I 스왑 새로운 Vector3의 y 및 z 값의 현재 설정을했다 한 모든 광고 교체, 그 Y 축 주위를 회전 카메라. 희망이 도움이!

+0

감사합니다! 내가 지금 시험에서보고있는 한 가지 이슈가 있긴하지만. 회전이 시작되면 다른 스 와이프 기능이 더 이상 작동하지 않습니다. 그래서 내가 측면으로 스 와이프하여 회전하면 더 이상 스 와이프 할 수 없습니다. 이상하게 보입니다. 그리고 이것이 빠른 해결책이라고 기대하고 있습니다. 또한 내부로 회전시키는 방법이 있습니까? 기껏해야 카메라가 바깥 쪽을 향하도록 회전합니다. 고마워요 :) – Natecurt3030

+0

재부팅 및 두 번째 테스트 후 문지름이 작동하는 것처럼 보입니다. 아마도 이상한 버그 일 것입니다. 그러나, 나는 아직도 어떤 정보든지 사람이 카메라가 내면을 향하게하는 회전을 가지고 관해 가지고 있을지도 모르는 것을 좋아할 것이다! – Natecurt3030

+0

그래서 여러분이 생각하는 것은 카메라의 로컬 축 중 하나가 아닌 카메라 외부의 한 지점을 중심으로 카메라를 회전시키는 것입니다. 먼저 카메라를 회전시킬 월드 스페이스에서 참조 점을 지정해야하므로 수행하기가 훨씬 더 어려워집니다. 예를 들어 카메라 앞에 20 단위가 고정되어 있거나 회전 할 사용자 정의 점/객체를 선택할 수 있습니다. 네가 뭘하고 있는지 모른 채, 나는별로 도움이 안돼. 미안합니다. – LWKatze

0

이 답변에 대한 내 이전 답변의 댓글 스레드를 참조하십시오.

카메라가 특정 지점을 중심으로 궤도에 진입하는 데는 두 가지 방법이 있습니다. 다른 작업을하기 전에 Unity에서 빈 GameObject를 생성하고 카메라를 궤도에 진입시키려는 고정 점에 설정하십시오. GameObject가 카메라의 시야에 있는지 확인하십시오. 그런 다음 카메라를 Empty GameObject의 부모로 삼으십시오.

쉬운 (그러나 더 단단한) 접근을 위해 TouchCamera 스크립트를 Empty GameObject에 연결하십시오. 카메라에서 TouchCamera 스크립트를 제거하십시오. 이제 스크립트의 Update 메서드 시작 부분 위에이 줄을 public Camera camera 추가하십시오. 스크립트에서 GetComponent<Camera>()의 모든 항목을 camera으로 바꿉니다. 스크립트를 저장하고 Unity로 돌아갑니다. 마지막으로 빈 GameObject를 클릭하고 카메라를 TouchCamera 구성 요소의 Serialized Camera 필드로 드래그하십시오. 이 접근법은 본질적으로 카메라의 제어를 Empty 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 구성 요소에는 "회전 중심"과 "카메라"라는 두 개의 필드가 있습니다. 빈 GameObject 및 카메라를 각각이 필드로 드래그하십시오. 이 스크립트를 생략하면이 스크립트는 Null 참조 오류를 발생시킵니다. 이제 막 치다.재생 창의 왼쪽 상단 모서리에있는 Toggle For Rotation 버튼을 클릭하면 마우스 포인터 또는 한 손가락을 화면 가운데로 드래그하여 카메라를 회전시킬 수 있습니다. Empty GameObject에서 카메라를 떼어 내면 스크립트가 계속 작동합니다. 또한 다른 Transform을 제공하여 우주의 어떤 지점을 도약 할 수 있습니다. 약간의 편집을 통해 Transform을 완전히 없애고 World Space에서 Vector3를 참조 점으로 사용할 수 있지만 transform.LookAt(CenterOfRotation); 행없이 카메라의 실제 회전을 직접 제어해야합니다. 대략 30 번째 줄, 145 번째 줄, 151 번째 줄에있는 3 개의 줄을 편집하여 회전축을 변경할 수 있습니다.

+0

와우! 진심으로 도와 주셔서 감사합니다! 고마워 – Natecurt3030