Files
3d-bianpo/Assets/Scripts/ControlMoveWithCollider.cs
2026-03-03 17:05:39 +08:00

176 lines
5.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using UnityEngine;
public class ControlMoveWithCollider : MonoBehaviour
{
public float moveSpeed = 50f; // 右键平移速度
public float zoomSpeed = 10f; // 滚轮缩放速度
public ClickToFocus inScript; // 引用焦点脚本,提供 core
public float rotationSensitivity = 0.2f; // 左键拖拽旋转灵敏度
//public float minPitch = -8f; // 最低俯仰角
//public float maxPitch = 80f; // 最高俯仰角
private Camera cam;
private bool isRotating = false;
private Vector2 lastMousePos;
private Vector3 reservoirCenter = new Vector3(1551f, 25f, 1119f);
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
cam = Camera.main;
Vector3 core = inScript.core;
if (inScript == null)
Debug.LogError("请在 Inspector 中把挂有 ClickToFocus 的物体拖给 inScript");
}
void Update()
{
//if (SliderDragDetector.isSliderDragging)
// return;
if (inScript == null) return;
Vector3 core = inScript.core;
// —— 右键平移 ——
if (Input.GetMouseButton(1))
{
moveSpeed = Vector3.Distance(core, transform.position) / 2f;//这里涉及到像素和实际空间米的关系转换
float mx = Input.GetAxis("Mouse X");
float my = Input.GetAxis("Mouse Y");
Vector3 desiredPosition = cam.transform.position + (-cam.transform.right * mx + -cam.transform.up * my) * moveSpeed * Time.deltaTime;
// 判断是否与障碍物发生碰撞
if (!WillCollideWithObstacle(desiredPosition))
{
cam.transform.position = desiredPosition;
}
}
// —— 滚轮缩放 ——
float scroll = Input.GetAxis("Mouse ScrollWheel");
if (Mathf.Abs(scroll) > 0.001f)
{
Vector3 desiredPosition = cam.transform.position + cam.transform.forward * scroll * zoomSpeed;
// 判断是否与障碍物发生碰撞
if (!WillCollideWithObstacle(desiredPosition))
{
cam.transform.position = desiredPosition;
}
}
// —— 左键开始/结束旋转 ——
if (Input.GetMouseButtonDown(0))
{
isRotating = true;
lastMousePos = Input.mousePosition;
}
if (Input.GetMouseButtonUp(0))
{
isRotating = false;
}
// —— 左键拖拽RotateAround 实现 + 俯仰限制 ——
if (isRotating && Input.GetMouseButton(0))
{
Vector2 curr = Input.mousePosition;
Vector2 delta = (curr - lastMousePos) * rotationSensitivity;
lastMousePos = curr;
/*
*/
// 1. 水平绕世界 Y 轴旋转
//Vector3 desiredPosition = cam.transform.position;
//cam.transform.RotateAround(core, Vector3.up, delta.x);
Vector3 localPosHorizonal = cam.transform.position - core;
Quaternion rotationHorizonal = Quaternion.AngleAxis(delta.x, Vector3.up);
Vector3 newLocalPosHorizonal = rotationHorizonal * localPosHorizonal;
Vector3 newPosHorizonal = core + newLocalPosHorizonal;
// 检查旋转后是否发生碰撞
if (!WillCollideWithObstacle(newPosHorizonal))
{
// 如果没有碰撞,执行旋转
cam.transform.RotateAround(core, Vector3.up, delta.x);
}
else
{
// 如果碰撞了,就不动
}
// 2. 俯仰旋转
Vector3 dir = (cam.transform.position - core).normalized;
Vector3 flat = new Vector3(dir.x, 0f, dir.z).normalized;
float selfFlatX = cam.transform.forward.x;
float selfFlatZ = cam.transform.forward.z;
Vector3 selfFlat = new Vector3(selfFlatX, 0f, selfFlatZ).normalized;
float selfPitch = Vector3.SignedAngle(selfFlat, cam.transform.forward, cam.transform.right);
if (selfPitch <= 80f && selfPitch >= 0f)
{
float pitchDelta = delta.y * -1f;
Vector3 localPosVertical = cam.transform.position - core;
Quaternion rotationVertical = Quaternion.AngleAxis(pitchDelta, cam.transform.right);
Vector3 newPosVertical = core + rotationVertical * localPosVertical;
if (!WillCollideWithObstacle(newPosVertical))
{
cam.transform.RotateAround(core, cam.transform.right, pitchDelta);
}
}
else if (selfPitch > 80f)
{
float pitchDelta = delta.y * -1f;
if (pitchDelta < 0f)
{
cam.transform.RotateAround(core, cam.transform.right, pitchDelta);
}
}
else if (selfPitch < 0f)
{
float pitchDelta = delta.y * -1f;
if (pitchDelta > 0f)
{
cam.transform.RotateAround(core, cam.transform.right, pitchDelta);
}
}
}
}
// 碰撞检测方法
bool WillCollideWithObstacle(Vector3 targetPosition)
{
// 计算从当前位置到目标位置的方向和距离
Vector3 moveDir = targetPosition - cam.transform.position;
float moveDist = moveDir.magnitude;
// 使用 SphereCast 检查即将到达的位置是否会与障碍物发生碰撞
RaycastHit hit;
if (Physics.SphereCast(cam.transform.position, 0.5f, moveDir, out hit, moveDist, LayerMask.GetMask("Default"), QueryTriggerInteraction.Collide) )
{
// 如果检测到碰撞,返回 true
Debug.Log("collider");
return true;
}
else if ( Mathf.Pow(targetPosition.x+120f, 2f)+ Mathf.Pow(targetPosition.z , 2f)<10000f && targetPosition.y<80f)
{
// 如果在范围内,返回 false
return false;
}
else
Debug.Log("outRange");
return true;//这个true是为了有返回值实际上走不到这一步
}
}