In Unity, how to control the horizontal and vertical movement, as well as rotation and panning, of a top-down camera (45-degree angle perspective)?

huangapple go评论75阅读模式
英文:

In Unity, how to control the horizontal and vertical movement, as well as rotation and panning, of a top-down camera (45-degree angle perspective)?

问题

我需要一个类似游戏《Frostpunk》的3D摄像机控制效果。我不知道如何使用欧拉角或四元数。最重要的是,当摄像机的Rotation.Y改变时,一切都变得不可预测。我需要一个公式或一段代码来解决这个问题。

我现在可以在世界坐标中正确地上下左右移动,但当局部坐标系与世界坐标系不同时,问题就出现了。

英文:

I need a 3D camera control effect like the game 'Frostpunk'. I don't know how to use Euler angles or quaternions. The most important thing is that everything becomes unpredictable when the camera's Rotation.Y changes. I need a formula or a piece of code to solve this problem.

I can now move correctly up, down, left, and right in world coordinates, but problems arise when the local coordinate system is different from the world coordinate system.

答案1

得分: 1

在Unity中控制顶视相机可能有些棘手,特别是如果你不熟悉欧拉角四元数的工作方式。然而,通过一些数学和一些Unity代码,你可以实现所需的相机行为。

这是一个示例脚本,可以帮助你控制顶视相机的水平和垂直移动,以及旋转和平移:

using UnityEngine;

public class TopDownCameraController : MonoBehaviour
{
    public Transform target; // 相机将跟随的对象
    public float distance = 10f; // 相机和目标之间的距离
    public float height = 10f; // 相机在目标上方的高度
    public float rotationSpeed = 10f; // 相机旋转的速度

    private float currentRotation = 0f; // 相机的当前旋转角度

    void LateUpdate()
    {
        // 获取水平和垂直输入
        float horizontalInput = Input.GetAxis("Horizontal");
        float verticalInput = Input.GetAxis("Vertical");

        // 根据输入计算目标位置
        Vector3 targetPosition = target.position + new Vector3(horizontalInput, 0f, verticalInput) * distance;

        // 将相机的位置设置为目标位置加上高度
        transform.position = new Vector3(targetPosition.x, targetPosition.y + height, targetPosition.z);

        // 根据输入和旋转速度计算旋转角度
        currentRotation += Input.GetAxis("Rotation") * rotationSpeed * Time.deltaTime;

        // 将相机的旋转设置为当前旋转角度
        transform.rotation = Quaternion.Euler(45f, currentRotation, 0f);

        // 根据输入计算平移
        float panInput = Input.GetAxis("Pan");

        // 根据平移输入水平移动相机的位置
        transform.position += transform.right * panInput;
    }
}

该脚本假定你有一个目标对象,相机将跟随该对象,并且相机最初位于目标正上方,具有45度角度的透视图。脚本使用LateUpdate()函数确保相机在目标移动后定位。

distance、height和rotationSpeed变量控制相机和目标之间的距离、相机在目标上方的高度以及相机旋转的速度。你可以调整这些变量以实现所需的相机行为。

脚本使用GetAxis()函数从用户那里获取水平、垂直、旋转和平移输入。这些输入用于计算相机的目标位置、旋转和平移。

currentRotation变量跟踪相机的当前旋转角度,根据旋转输入和旋转速度进行更新。

最后,脚本根据平移输入水平移动相机的位置。

英文:

Controlling a top-down camera in Unity can be a bit tricky, especially if you're new to working with Euler angles or quaternions. However, with a bit of math and some Unity code, you can achieve the desired camera behavior.

Here is an example script that should help you control the horizontal and vertical movement, as well as rotation and panning of a top-down camera:

Example:

using UnityEngine;

public class TopDownCameraController : MonoBehaviour
{
    public Transform target; // The object the camera will follow
    public float distance = 10f; // The distance between the camera and the target
    public float height = 10f; // The height of the camera above the target
    public float rotationSpeed = 10f; // The speed at which the camera rotates

    private float currentRotation = 0f; // The current rotation of the camera

    void LateUpdate()
    {
        // Get the horizontal and vertical inputs
        float horizontalInput = Input.GetAxis("Horizontal");
        float verticalInput = Input.GetAxis("Vertical");

        // Calculate the target position based on the inputs
        Vector3 targetPosition = target.position + new Vector3(horizontalInput, 0f, verticalInput) * distance;

        // Set the camera's position to the target position plus the height
        transform.position = new Vector3(targetPosition.x, targetPosition.y + height, targetPosition.z);

        // Calculate the rotation based on the inputs and the rotation speed
        currentRotation += Input.GetAxis("Rotation") * rotationSpeed * Time.deltaTime;

        // Set the camera's rotation to the current rotation
        transform.rotation = Quaternion.Euler(45f, currentRotation, 0f);

        // Calculate the panning based on the inputs
        float panInput = Input.GetAxis("Pan");

        // Move the camera's position horizontally based on the panning input
        transform.position += transform.right * panInput;
    }
}

This script assumes that you have a target object that the camera will follow, and that the camera is initially positioned directly above the target with a 45-degree angle perspective. The script uses the LateUpdate() function to ensure that the camera is positioned after the target has moved.

The distance, height, and rotationSpeed variables control the distance between the camera and the target, the height of the camera above the target, and the speed at which the camera rotates, respectively. You can adjust these variables to achieve the desired camera behavior.

The script uses the GetAxis() function to get the horizontal, vertical, rotation, and pan inputs from the user. These inputs are used to calculate the target position, the rotation, and the panning of the camera.

The currentRotation variable keeps track of the current rotation of the camera, which is updated based on the rotation input and the rotation speed.

Finally, the script moves the camera's position horizontally based on the panning input.

答案2

得分: 0

I understand your frustration, camera control can be tricky in 3D space. This script uses Euler angles to control the camera, so you don't need to worry about quaternions.

public class CameraController : MonoBehaviour
{
    public Transform target;
    public float distance = 5.0f;
    public float height = 2.0f;
    public float rotationDamping = 3.0f;
    public float heightDamping = 2.0f;
    public float zoomDamping = 2.0f;
    public float minZoomDistance = 2.0f;
    public float maxZoomDistance = 10.0f;

    private void LateUpdate()
    {
        if (!target)
            return;

        float currentRotationAngle = transform.eulerAngles.y;
        float currentHeight = transform.position.y;

        float desiredRotationAngle = target.eulerAngles.y;
        float desiredHeight = target.position.y + height;

        currentHeight = Mathf.Lerp(currentHeight, desiredHeight, heightDamping * Time.deltaTime);
        currentRotationAngle = Mathf.LerpAngle(currentRotationAngle, desiredRotationAngle, rotationDamping * Time.deltaTime);

        Quaternion currentRotation = Quaternion.Euler(0, currentRotationAngle, 0);

        float desiredDistance = Mathf.Clamp(distance - Input.GetAxis("Mouse ScrollWheel") * zoomDamping, minZoomDistance, maxZoomDistance);
        Vector3 zoomVector = new Vector3(0, 0, -desiredDistance);
        Vector3 position = target.position + (currentRotation * zoomVector);

        transform.position = Vector3.Lerp(transform position, position, Time.deltaTime * zoomDamping);
        transform.position = new Vector3(transform.position.x, currentHeight, transform.position.z);

        transform.LookAt(target);
    }
}

You may use this script to attach it to the camera object in your scene.

英文:

I understand your frustration , camera control can be tricky in 3D space.This script uses Euler angles to control the camera, so you don't need to worry about quaternions.

public class CameraController : MonoBehaviour
{
    public Transform target;
    public float distance = 5.0f;
    public float height = 2.0f;
    public float rotationDamping = 3.0f;
    public float heightDamping = 2.0f;
    public float zoomDamping = 2.0f;
    public float minZoomDistance = 2.0f;
    public float maxZoomDistance = 10.0f;

    private void LateUpdate()
    {
        if (!target)
            return;

        float currentRotationAngle = transform.eulerAngles.y;
        float currentHeight = transform.position.y;

        float desiredRotationAngle = target.eulerAngles.y;
        float desiredHeight = target.position.y + height;

        currentHeight = Mathf.Lerp(currentHeight, desiredHeight, heightDamping * Time.deltaTime);
        currentRotationAngle = Mathf.LerpAngle(currentRotationAngle, desiredRotationAngle, rotationDamping * Time.deltaTime);

        Quaternion currentRotation = Quaternion.Euler(0, currentRotationAngle, 0);

        float desiredDistance = Mathf.Clamp(distance - Input.GetAxis("Mouse ScrollWheel") * zoomDamping, minZoomDistance, maxZoomDistance);
        Vector3 zoomVector = new Vector3(0, 0, -desiredDistance);
        Vector3 position = target.position + (currentRotation * zoomVector);

        transform.position = Vector3.Lerp(transform.position, position, Time.deltaTime * zoomDamping);
        transform.position = new Vector3(transform.position.x, currentHeight, transform.position.z);

        transform.LookAt(target);
    }
}

** You may use this script to attach it to the camera object in your scene

huangapple
  • 本文由 发表于 2023年3月8日 16:08:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/75670616.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定