Проблема с вращением камеры в Unity3D C # (вероятно, легко исправить)

c# android unity3d camera rotation

502 просмотра

2 ответа

31 Репутация автора

У меня есть некоторый CS-код, который я пытаюсь использовать в единстве для поворота камеры вокруг оси Y. Проблема в том, что камера в данный момент вращается вокруг оси z, что вызывает некоторые визуальные трудности в моей игре.

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

Я и художник и ни в коем случае не кодер, и этот код не мое творение. Я просто ищу помощь в исправлении этого в соответствии с моими потребностями. Так что, если кто-то может сообщить мне наиболее простую настройку, которую я могу внести в этот текущий код, я был бы очень признателен. Я знаю, что это не самый обычный вопрос, я просто надеюсь на небольшую помощь.

Автор: Natecurt3030 Источник Размещён: 19.07.2016 02:44

Ответы (2)


1 плюс

103 Репутация автора

Решение

Вы правы - это действительно легко исправить. Все, что вам нужно сделать, чтобы изменить ось вращения, это настроить следующую строку (примерно строка 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));

Все, что я сделал, это поменял местами текущие настройки значений y и z в новом Vector3. Надеюсь это поможет!

Автор: LWKatze Размещён: 19.07.2016 04:13

0 плюса

103 Репутация автора

Смотрите ветку комментариев моего предыдущего ответа для контекста этого ответа.

Есть два подхода, чтобы заставить вашу камеру вращаться вокруг точки. Прежде чем делать что-либо еще, создайте пустой GameObject в Unity и установите его в фиксированной точке, вокруг которой вы хотите, чтобы ваша камера вращалась. Убедитесь, что GameObject находится в зоне прямой видимости камеры. Затем добавьте камеру в пустой GameObject.

Для более простого (но более жесткого) подхода прикрепите скрипт TouchCamera к пустому объекту GameObject. Удалите скрипт TouchCamera из вашей камеры. Теперь добавьте эту строку public Camera cameraнад началом метода Update в скрипте. В вашем скрипте заменить все вхождения GetComponent<Camera>()с camera. Сохраните ваш скрипт и вернитесь в Unity. Наконец, щелкните пустой игровой объект и перетащите камеру в поле «Серийная камера» в компоненте TouchCamera. Этот подход существенно перемещает управление камерой в пустой 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;
}

}

Теперь прикрепите это к вашей камере (которая должна быть дочерней по отношению к пустому GameObject) и удалите скрипт TouchCamera. Вы заметите два поля внутри компонента CameraControl, одно из которых читается как «Центр вращения», а другое - как «Камера». Перетащите пустой GameObject и вашу камеру на эти поля соответственно. Этот скрипт будет выдавать нулевые ссылочные ошибки, если вы пропустите этот шаг. Теперь просто нажмите Play. Когда вы нажимаетеToggle For RotationКнопка в верхнем левом углу окна воспроизведения, вы сможете вращать камеру, перетаскивая указатель мыши или один палец вокруг центра экрана. Вы можете отключить камеру от пустого игрового объекта, и скрипт все равно будет работать. Вы также можете вращаться вокруг любой точки пространства, предоставляя другое преобразование. С небольшим количеством редактирования, можно также устранить Transform полностью и использовать Vector3 в качестве опорной точки в мировом пространстве, но вам нужно будет контролировать фактическое вращение камеры на себя без линии transform.LookAt(CenterOfRotation);. Вы можете изменить ось вращения, отредактировав три строки, расположенные примерно в строке 30, строке 145 и строке 151.

Автор: LWKatze Размещён: 20.07.2016 06:38
Вопросы из категории :
32x32