aboutsummaryrefslogtreecommitdiff
path: root/Assets/Scripts/CameraHandler.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Assets/Scripts/CameraHandler.cs')
-rw-r--r--Assets/Scripts/CameraHandler.cs146
1 files changed, 105 insertions, 41 deletions
diff --git a/Assets/Scripts/CameraHandler.cs b/Assets/Scripts/CameraHandler.cs
index b0b8a70..e170503 100644
--- a/Assets/Scripts/CameraHandler.cs
+++ b/Assets/Scripts/CameraHandler.cs
@@ -8,113 +8,177 @@ namespace DS
{
public class CameraHandler : MonoBehaviour
{
- public Transform cameraTransform;
- public Transform targetTransform;
- public Transform cameraPivotTransform;
- private Transform _myTransform;
- private Vector3 _cameraTransformPosition;
- private LayerMask _ignoreLayers;
- private Vector3 cameraFollowVelocity = Vector3.zero;
-
- private bool _cursorLocked = false;
-
- public static CameraHandler singleton;
- public float lookSpeed = 0.1f;
- public float followSpeed = 0.1f;
- public float pivotSpeed = 0.03f;
-
- private float _targetPosition;
- private float _defaultPosition;
- private float _lookAngle;
- private float _pivotAngle;
- public float minimumPivot = -35;
- public float maximumPivot = 35;
-
- public float cameraSphereRadius = 0.2f;
- public float cameraCollisionOffSet = 0.2f;
- public float minimumCollisionOffSet = 0.2f;
-
+ // ========== 公开引用 ==========
+ [Header("Camera Transforms")]
+ public Transform cameraTransform; // 摄像机 Transform(子物体)
+ public Transform targetTransform; // 跟踪目标(如玩家角色)
+ public Transform cameraPivotTransform; // 摄像机枢轴 Transform(用于俯仰旋转)
+
+ // ========== 私有引用与状态 ==========
+ private Transform _myTransform; // 当前对象的 Transform 缓存
+ private Vector3 _cameraTransformPosition; // 用于 Lerp 的摄像机局部位置
+ private LayerMask _ignoreLayers; // 忽略的碰撞层(玩家、UI 等)
+ private Vector3 cameraFollowVelocity = Vector3.zero; // SmoothDamp 速度参考值
+
+ private bool _cursorLocked = false; // 鼠标是否锁定
+
+ // ========== 单例 ==========
+ public static CameraHandler singleton; // 全局访问实例
+
+ // ========== 速度参数(可调) ==========
+ [Header("Movement Speeds")]
+ public float lookSpeed = 0.1f; // 水平旋转速度
+ public float followSpeed = 0.1f; // 跟随目标的速度
+ public float pivotSpeed = 0.03f; // 俯仰旋转速度
+
+ // ========== 内部状态 ==========
+ private float _targetPosition; // 摄像机与枢轴的目标距离
+ private float _defaultPosition; // 摄像机的默认 Z 轴局部位置(距离)
+ private float _lookAngle; // 水平旋转角度(Y 轴)
+ private float _pivotAngle; // 俯仰旋转角度(X 轴)
+
+ [Header("Pivot Clamps")]
+ public float minimumPivot = -35; // 俯仰最小角度
+ public float maximumPivot = 35; // 俯仰最大角度
+
+ // ========== 碰撞检测参数 ==========
+ [Header("Collision Settings")]
+ public float cameraSphereRadius = 0.2f; // 球体投射的半径
+ public float cameraCollisionOffSet = 0.2f; // 碰撞后摄像机偏移量
+ public float minimumCollisionOffSet = 0.2f; // 最小偏移量,防止穿透
+
+ // ====================================================================
+ // Awake:初始化引用与默认值
+ // ====================================================================
private void Awake()
{
- singleton = this;
- _myTransform = transform;
- _defaultPosition = cameraTransform.localPosition.z;
+ singleton = this; // 设置单例
+ _myTransform = transform; // 缓存自身 Transform
+ _defaultPosition = cameraTransform.localPosition.z; // 记录默认 Z 距离
+ // 忽略层级:8(玩家)、9、10;使用位取反运算
_ignoreLayers = ~(1 << 8 | 1 << 9 | 1 << 10);
}
+ // ====================================================================
+ // Update:每帧检测鼠标锁定状态
+ // ====================================================================
private void Update()
{
UpdateCursorLock();
}
+ // ====================================================================
+ // UpdateCursorLock:管理鼠标锁定与可见性
+ // ====================================================================
private void UpdateCursorLock()
{
+ // 左键点击 -> 锁定鼠标(游戏控制模式)
if (Input.GetMouseButtonDown(0))
{
- Cursor.lockState = CursorLockMode.Locked;
- Cursor.visible = false;
+ Cursor.lockState = CursorLockMode.Locked; // 锁定鼠标到窗口中心
+ Cursor.visible = false; // 隐藏鼠标
_cursorLocked = true;
}
+ // 按下 Escape -> 解锁鼠标(UI / 菜单模式)
if (Input.GetKeyDown(KeyCode.Escape))
{
- Cursor.lockState = CursorLockMode.None;
- Cursor.visible = true;
+ Cursor.lockState = CursorLockMode.None; // 释放鼠标
+ Cursor.visible = true; // 显示鼠标
_cursorLocked = false;
}
}
+ // ====================================================================
+ // FollowTarget:平滑跟随目标,并处理摄像机碰撞
+ // ====================================================================
public void FollowTarget(float delta)
{
- Vector3 targetPosition = Vector3.SmoothDamp(_myTransform.position, targetTransform.position,
- ref cameraFollowVelocity, delta / followSpeed);
+ // 使用 SmoothDamp 平滑移动到目标位置
+ Vector3 targetPosition = Vector3.SmoothDamp(
+ _myTransform.position,
+ targetTransform.position,
+ ref cameraFollowVelocity,
+ delta / followSpeed);
+
_myTransform.position = targetPosition;
-
+
+ // 处理摄像机与场景物体的碰撞
HandleCameraCollisions(delta);
}
+ // ====================================================================
+ // HandleCameraRotation:处理鼠标输入的摄像机旋转
+ // ====================================================================
public void HandleCameraRotation(float delta, float mouseInputX, float mouseInputY)
{
+ // 鼠标未锁定时不处理旋转
if (!_cursorLocked)
return;
-
+
+ // 累加水平旋转角度(左右)
_lookAngle += (mouseInputX * lookSpeed) / delta;
+ // 累加俯仰旋转角度(上下,取反使鼠标向上移动时视角向上)
_pivotAngle -= (mouseInputY * pivotSpeed) / delta;
+ // 限制俯仰角度范围,防止视角翻转
_pivotAngle = Mathf.Clamp(_pivotAngle, minimumPivot, maximumPivot);
+ // 应用水平旋转到当前对象(Y 轴旋转)
Vector3 rotation = Vector3.zero;
rotation.y = _lookAngle;
Quaternion targetRotation = Quaternion.Euler(rotation);
_myTransform.rotation = targetRotation;
+ // 应用俯仰旋转到枢轴对象(X 轴旋转,局部坐标)
rotation = Vector3.zero;
rotation.x = _pivotAngle;
-
targetRotation = Quaternion.Euler(rotation);
cameraPivotTransform.localRotation = targetRotation;
}
+ // ====================================================================
+ // HandleCameraCollisions:检测并避免摄像机与场景物体穿插
+ // ====================================================================
public void HandleCameraCollisions(float delta)
{
+ // 目标距离默认设为默认距离
_targetPosition = _defaultPosition;
+
RaycastHit hit;
+
+ // 计算从枢轴指向摄像机的方向向量
Vector3 direction = cameraTransform.position - cameraPivotTransform.position;
direction.Normalize();
- if (Physics.SphereCast(cameraPivotTransform.position,cameraSphereRadius,direction,out hit,Mathf.Abs(_targetPosition)))
+ // 从枢轴位置沿 direction 方向进行 SphereCast 检测
+ // 检测距离为 _targetPosition 的绝对值
+ if (Physics.SphereCast(
+ cameraPivotTransform.position,
+ cameraSphereRadius,
+ direction,
+ out hit,
+ Mathf.Abs(_targetPosition)))
{
+ // 计算枢轴到碰撞点的实际距离
float dis = Vector3.Distance(cameraPivotTransform.position, hit.point);
+ // 摄像机应位于碰撞点前方 cameraCollisionOffSet 处
_targetPosition = -(dis - cameraCollisionOffSet);
}
+ // 如果计算出的目标距离绝对值太小,强制使用最小值防止视觉异常
if (Mathf.Abs(_targetPosition) < minimumCollisionOffSet)
{
_targetPosition = -minimumCollisionOffSet;
}
- _cameraTransformPosition.z = Mathf.Lerp(cameraTransform.localPosition.z, _targetPosition, delta / 0.2f);
+ // 使用 Lerp 平滑调整摄像机的局部 Z 轴位置
+ _cameraTransformPosition.z = Mathf.Lerp(
+ cameraTransform.localPosition.z,
+ _targetPosition,
+ delta / 0.2f);
+
+ // 应用位置
cameraTransform.localPosition = _cameraTransformPosition;
}
}
}
-