124 lines
4.1 KiB
C#
124 lines
4.1 KiB
C#
|
|
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);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|