Search code examples
c#unity-game-engine3dcamera

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


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.


Solution

  • 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