I completed a camera tutorial for Unity. I can rotate a camera around my figure around the Y axis (Vector3.up) and I wanted to extend that for a Fixed-Free 3rd Person camera (What are the types of 3rd-person camera called?) where I can tilt aswell but I am stuck with the wrong rotation.
I expect the camera to go up/down whenever I use the joystick up/down and always go left/right when I use the joystick left/right.
But instead of that I get always left/right movement as I wish but up/down is only working at the center. The further I go left or right (see images) the less I go up/down. This sounds super complicated, please see the images. I want the same behaviour as shown when the camera is behind the object and I want to avoid the behaviour at the right side like in the first image.
Bonus would be if I can limit the up and down movement to say 160° so the player can't look top down.
The Code looks like this (only RotateCamera() and UpdateCameraPosition() are relevant):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerCamera : MonoBehaviour
{
[System.Serializable]
public class InputSettings : System.Object
{
public float inputThreshold = 0.1f;
public string VERTICAL_AXIS = "CameraVertical";
public string HORIZONTAL_AXIS = "CameraHorizontal";
public string LOCK_TARGET_PYRAMID = "LockToPyramid";
public string LOCK_TARGET_AREA = "LockToArea";
}
[SerializeField] private Transform target;
[SerializeField] private float cameraSpeed = 2;
[SerializeField] private Vector3 lookAtPlayerOffset = new Vector3(0f, 0.6f);
private PlayerController playerController;
private float cameraHorizontal, cameraVertical;
private float lockPyramid, lockArea;
private InputSettings inputSettings;
private Vector3 cameraPlayerOffset;
void Start()
{
SetCameraTarget(target);
inputSettings = new InputSettings();
cameraPlayerOffset = transform.position - playerController.transform.position;
}
private void Update()
{
GetInput();
}
private void LateUpdate()
{
RotateCamera();
UpdateCameraPosition();
}
private void RotateCamera()
{
Quaternion cameraRotationXDelta = Quaternion.AngleAxis(cameraHorizontal * cameraSpeed, Vector3.up);
Quaternion cameraRotationYDelta = Quaternion.AngleAxis(cameraVertical * cameraSpeed, Vector3.right);
// this does not work how I wish it would after rotating around a bit
cameraPlayerOffset = cameraRotationYDelta * cameraRotationXDelta * cameraPlayerOffset;
}
private void UpdateCameraPosition()
{
// prevent camera from clipping through floor
Vector3 newPos = playerController.transform.position + cameraPlayerOffset;
newPos.y = newPos.y < 0.2f ? newPos.y = 0.2f : newPos.y;
transform.position = newPos;
transform.LookAt(target.transform.position + lookAtPlayerOffset);
}
private void GetInput()
{
cameraHorizontal = Input.GetAxis(inputSettings.HORIZONTAL_AXIS); // interpolated
cameraVertical = Input.GetAxis(inputSettings.VERTICAL_AXIS); // interpolated
lockPyramid = Input.GetAxis(inputSettings.LOCK_TARGET_PYRAMID); // interpolated
lockArea = Input.GetAxis(inputSettings.LOCK_TARGET_AREA); // interpolated
}
private void SetCameraTarget(Transform targetTransform)
{
target = targetTransform;
if (target != null)
{
if (target.GetComponent<PlayerController>())
{
playerController = target.GetComponent<PlayerController>();
}
else
{
Debug.LogError("The camera's target needs a player character controller.");
}
}
else
{
Debug.LogError("Your camera needs a target");
}
}
}