This commit is contained in:
zhangjiajia
2026-03-05 11:30:53 +08:00
parent 4491b8d9ee
commit dcf1199970
755 changed files with 78018 additions and 0 deletions

View File

@@ -0,0 +1,305 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class CameraControl : MonoBehaviour
{
[Header("移动速度")]
public float moveSpeed = 1.2f;
[Header("旋转速度")]
public float rotateSpeed = 45f;
[Header("缩放速度")]
public float zoomSpeed = 0.2f;
[Header("最小高度")]
public float minHeight = 0.1f;
[Header("最大高度")]
public float maxHeight = 100f;
[Header("地图中心")]
public Vector3 mapCenter = Vector3.zero;
[Header("最大距离")]
public float maxDistance = 3000f;
[Header("最小角度")]
public float minAngleX = -60f;
[Header("最大角度")]
public float maxAngleX = 88f;
[Header("射线检测提前量")]
public float raycastOffset = 0.1f; // 射线检测提前量
//控制变量
private Vector3 viewPos_0; //鼠标左键初始坐标
private Vector3 viewPos_1; //鼠标右键初始坐标
private Vector3 startCameraPos; //相机初始位置
private Vector3 targetCameraPos; //相机目标位置
private Vector2 startCameraEuler; //初始角度
private Vector2 targetCameraEuler; //目标角度
//相机控制
private Camera mainCamera;
private bool isCameraCtrl = true; //相机是否可控制
private float screenAdapter = 1f; //屏幕长度比
//相机操作有效性判断
private bool isClickUI = false;
private void Awake()
{
mainCamera = Camera.main;
screenAdapter = Screen.width / (float)Screen.height;
targetCameraPos = transform.position;
targetCameraEuler = transform.eulerAngles;
}
void Update()
{
//相机控制
if (isCameraCtrl)
{
//操作有效性判断
if (EventSystem.current != null)
{
if (Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1) || Input.GetMouseButtonDown(2))
{
isClickUI = EventSystem.current.IsPointerOverGameObject();
}
if (Input.GetMouseButtonUp(0) || Input.GetMouseButtonUp(1) || Input.GetMouseButtonUp(2))
{
isClickUI = false;
}
}
if (!isClickUI)
{
//平移控制
if (Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(2))
{
viewPos_0 = mainCamera.ScreenToViewportPoint(Input.mousePosition);
startCameraPos = transform.position;
startCameraEuler = transform.eulerAngles;
}
if (Input.GetMouseButton(0) || Input.GetMouseButton(2))
{
Vector3 currentViewPos = mainCamera.ScreenToViewportPoint(Input.mousePosition);
Vector3 dis = currentViewPos - viewPos_0;
dis = dis * GetMoveSpeed();
// 获取相机的右向量和上向量
Vector3 right = transform.right;
Vector3 up = transform.up;
// 分别计算水平和垂直方向的位移
float horizontalDis = -dis.x * screenAdapter;
float verticalDis = -dis.y * screenAdapter;
// 根据相机的右向量和上向量计算最终位移
Vector3 finalDis = right * horizontalDis + up * verticalDis;
// targetCameraPos = startCameraPos + finalDis;
Vector3 newTargetPos = startCameraPos + finalDis;
newTargetPos = CheckCollisionOnMove(transform.position, newTargetPos);
targetCameraPos = newTargetPos;
}
//旋转控制
if (Input.GetMouseButtonDown(1))
{
viewPos_1 = mainCamera.ScreenToViewportPoint(Input.mousePosition);
startCameraPos = transform.position;
startCameraEuler = transform.eulerAngles;
}
if (Input.GetMouseButton(1))
{
Vector2 angle = (mainCamera.ScreenToViewportPoint(Input.mousePosition) - viewPos_1) * rotateSpeed;
angle = new Vector3(-angle.y, angle.x * screenAdapter);
targetCameraEuler = startCameraEuler + angle;
}
//缩进控制
if (Input.mouseScrollDelta != Vector2.zero)
{
// float moveSpeed = GetMoveSpeed() * 0.2f;
// targetCameraPos += transform.forward * moveSpeed * Input.mouseScrollDelta.y;
float moveSpeed = GetMoveSpeed() * zoomSpeed;
Vector3 newTargetPos = targetCameraPos + transform.forward * moveSpeed * Input.mouseScrollDelta.y;
newTargetPos = CheckCollisionOnMove(transform.position, newTargetPos);
targetCameraPos = newTargetPos;
}
//相机运动
LimitCamera();
// CheckCollision(); // 检查碰撞
//控制相机运动
// 控制相机运动
if (Vector3.Distance(transform.position, targetCameraPos) > 0.1f)
{
transform.position = Vector3.Lerp(transform.position, targetCameraPos, 5f * Time.deltaTime);
// Debug.Log("position"+transform.position);
}
// 控制相机旋转
if (Quaternion.Angle(transform.rotation, Quaternion.Euler(targetCameraEuler)) > 0.1f)
{
transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.Euler(targetCameraEuler), 5f * Time.deltaTime);
// Debug.Log("rotation"+transform.eulerAngles);
}
}
}
}
//开启相机控制
// public void StartCameraControl()
// {
// isCameraCtrl = true;
// isClickUI = false;
// viewPos_0 = mainCamera.ScreenToViewportPoint(Input.mousePosition);
// viewPos_1 = mainCamera.ScreenToViewportPoint(Input.mousePosition);
// startCameraPos = transform.position;
// startCameraEuler = transform.eulerAngles;
// targetCameraPos = transform.position;
// targetCameraEuler = transform.eulerAngles;
// }
//停止相机控制
// public void StopCameraControl()
// {
// isCameraCtrl = false;
// }
//获取相机移动速度
float GetMoveSpeed()
{
float highDis = (transform.position.y - minHeight);
float speed = moveSpeed + moveSpeed * highDis;
speed = Mathf.RoundToInt(speed);
return speed;
}
//限制相机位置,角度
void LimitCamera()
{
//位置限制
targetCameraPos.y = Mathf.Clamp(targetCameraPos.y, minHeight, maxHeight);
float dis = Vector3.Distance(targetCameraPos, mapCenter);
if (dis > maxDistance)
{
Vector3 dir = (targetCameraPos - mapCenter).normalized;
targetCameraPos = mapCenter + dir * maxDistance;
}
//角度限制
if (targetCameraEuler.x > 180) { targetCameraEuler.x -= 360f; }
if (targetCameraEuler.x < -180) { targetCameraEuler.x += 360; }
if (targetCameraEuler.y > 180) { targetCameraEuler.y -= 360f; }
if (targetCameraEuler.y < -180) { targetCameraEuler.y += 360; }
targetCameraEuler.x = Mathf.Clamp(targetCameraEuler.x, minAngleX, maxAngleX);
}
// // 检查碰撞
// void CheckCollisionOnMove(Vector3 startPos, Vector3 targetPos)
// {
// RaycastHit hit;
// Vector3 direction = targetCameraPos - transform.position;
// float distance = direction.magnitude;
// if (Physics.Raycast(transform.position, direction.normalized, out hit, distance))
// {
// targetCameraPos = hit.point;
// }
// }
// 修改CheckCollisionOnMove方法增加垂直方向检测
Vector3 CheckCollisionOnMove(Vector3 startPos, Vector3 targetPos)
{
Vector3 direction = targetPos - startPos;
float distance = direction.magnitude;
// 存储最终的安全位置
Vector3 safePosition = targetPos;
// 1. 检测移动路径上的障碍物(包括水平和垂直方向)
if (distance > 0)
{
float sphereRadius = 0.1f; // 根据相机碰撞体大小调整
// 计算起点和终点的包围盒
Bounds startBounds = new Bounds(startPos, Vector3.one * sphereRadius * 2);
Bounds endBounds = new Bounds(targetPos, Vector3.one * sphereRadius * 2);
// 创建从起点到终点的包围盒移动路径
Bounds movementBounds = new Bounds();
movementBounds.Encapsulate(startBounds);
movementBounds.Encapsulate(endBounds);
// 使用多个方向的射线检测全方位碰撞
bool collisionDetected = false;
// 主方向检测
if (Physics.SphereCast(startPos, sphereRadius, direction.normalized, out RaycastHit hit, distance + raycastOffset))
{
float safeDistance = hit.distance - raycastOffset - sphereRadius;
safePosition = startPos + direction.normalized * Mathf.Max(safeDistance, 0);
collisionDetected = true;
}
// 如果是向上移动,增加顶部检测
if (direction.y > 0.1f) // 设置一个阈值,只在明显向上移动时检测
{
Vector3 topStart = startPos + Vector3.up * sphereRadius;
Vector3 topDirection = Vector3.up * (endBounds.max.y - startBounds.max.y);
if (Physics.SphereCast(topStart, sphereRadius, topDirection.normalized, out hit, topDirection.magnitude + raycastOffset))
{
float verticalSafeDistance = hit.distance - raycastOffset - sphereRadius;
safePosition.y = startPos.y + verticalSafeDistance;
collisionDetected = true;
}
}
if (collisionDetected)
{
// 声明地面检测变量(移到这里避免作用域冲突)
Ray groundRay1;
float maxGroundDistance1;
RaycastHit groundHit1;
// 如果检测到碰撞,进行地面高度验证
groundRay1 = new Ray(safePosition + Vector3.up, Vector3.down);
maxGroundDistance1 = 0.5f;
if (Physics.Raycast(groundRay1, out groundHit1, maxGroundDistance1))
{
float minSafeHeight = groundHit1.point.y + minHeight;
if (safePosition.y < minSafeHeight)
{
safePosition.y = minSafeHeight;
}
}
return safePosition;
}
}
// 2. 如果没有检测到碰撞,只进行地面高度验证
// 重用之前声明的变量
Ray groundRay = new Ray(targetPos + Vector3.up, Vector3.down);
float maxGroundDistance = 0.5f;
if (Physics.Raycast(groundRay, out RaycastHit groundHit, maxGroundDistance))
{
float minSafeHeight = groundHit.point.y + minHeight;
if (targetPos.y < minSafeHeight)
{
targetPos.y = minSafeHeight;
}
}
return targetPos;
}
}