Files
TopDown/Assets/Scripts/CameraController.cs

124 lines
4.1 KiB
C#
Raw Normal View History

2026-08-04 16:56:27 +01:00
using UnityEngine;
using UnityEngine.InputSystem;
public class CameraController : MonoBehaviour
{
[Header("Target Tracking")]
[SerializeField] private Transform target;
[SerializeField] private Vector3 targetOffset = new Vector3(0, 1.5f, 0);
[Header("Orbit & Distance Settings")]
[SerializeField] private float distance = 12.0f;
[SerializeField] private float minDistance = 5.0f;
[SerializeField] private float maxDistance = 25.0f;
[Header("Rotation Limits & Speed")]
[SerializeField] private float rotationSpeed = 60.0f; // degrees per second for Q/E yaw
[SerializeField] private float tiltSpeed = 45.0f; // degrees per second for W/S pitch
[SerializeField] private float minPitch = 15.0f; // Minimum angle looking up/down
[SerializeField] private float maxPitch = 80.0f; // Maximum top-down angle
[Header("Smooth Movement")]
[SerializeField] private float smoothSpeed = 10.0f;
private float currentYaw = 0.0f; // Horizontal rotation angle around target
private float currentPitch = 45.0f; // Vertical tilt angle
private void Start()
{
// Auto-find player target if not assigned
if (target == null)
{
GameObject player = GameObject.FindWithTag("Player");
if (player != null)
{
target = player.transform;
}
else
{
PlayerController pc = FindFirstObjectByType<PlayerController>();
if (pc != null) target = pc.transform;
}
}
// Initialize angles from starting rotation
Vector3 angles = transform.eulerAngles;
currentYaw = angles.y;
currentPitch = angles.x;
}
private void LateUpdate()
{
if (target == null) return;
HandleCameraInput();
UpdateCameraPosition();
}
private void HandleCameraInput()
{
Keyboard currentKeyboard = Keyboard.current;
if (currentKeyboard == null) return;
// Q and E: Rotate Yaw around Player
if (currentKeyboard.qKey.isPressed)
{
currentYaw -= rotationSpeed * Time.deltaTime;
}
if (currentKeyboard.eKey.isPressed)
{
currentYaw += rotationSpeed * Time.deltaTime;
}
// W and S: Tilt Pitch up and down
if (currentKeyboard.wKey.isPressed)
{
currentPitch += tiltSpeed * Time.deltaTime;
}
if (currentKeyboard.sKey.isPressed)
{
currentPitch -= tiltSpeed * Time.deltaTime;
}
// Clamp vertical tilt so camera doesn't flip or go beneath ground
currentPitch = Mathf.Clamp(currentPitch, minPitch, maxPitch);
// Optional Zoom via Mouse Scroll
Mouse currentMouse = Mouse.current;
if (currentMouse != null)
{
float scroll = currentMouse.scroll.ReadValue().y;
if (Mathf.Abs(scroll) > 0.01f)
{
distance -= Mathf.Sign(scroll) * 1.5f;
distance = Mathf.Clamp(distance, minDistance, maxDistance);
}
}
}
private void UpdateCameraPosition()
{
// Calculate focus point on player
Vector3 focusPoint = target.position + targetOffset;
// Calculate orbit rotation & offset vector
Quaternion rotation = Quaternion.Euler(currentPitch, currentYaw, 0);
Vector3 negDistance = new Vector3(0.0f, 0.0f, -distance);
Vector3 targetCameraPos = focusPoint + (rotation * negDistance);
// Smoothly interpolate camera position and rotation
transform.position = Vector3.Lerp(transform.position, targetCameraPos, smoothSpeed * Time.deltaTime);
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, smoothSpeed * Time.deltaTime);
}
private void OnDrawGizmosSelected()
{
if (target != null)
{
Gizmos.color = Color.cyan;
Gizmos.DrawWireSphere(target.position + targetOffset, 0.5f);
Gizmos.DrawLine(transform.position, target.position + targetOffset);
}
}
}