using UnityEngine; using UnityEngine.UI; using DG.Tweening; using TMPro; public class MouseFollowAndZoom : MonoBehaviour { public float parallaxEffectMultiplier = 0.1f; public Vector2 maxOffset = new Vector2(2f, 2f); public GameObject targetIndicator; // UI 目标框 public TMP_Text targetNameText; // 显示目标名称的文本 public Button exitZoomButton; // 退出缩放的按钮 public float zoomInScale = 1.5f; // 缩放倍数 public float zoomDuration = 1.0f; // 缩放持续时间(减慢) public Vector2 sceneBoundsMin; // 场景边界的左下角 public Vector2 sceneBoundsMax; // 场景边界的右上角 private Camera mainCamera; private Vector3 initialPosition; private Vector3 zoomedInPosition; // 保存缩放时的相机位置 private bool isZoomedIn = false; private Transform currentTarget; void Start() { mainCamera = Camera.main; initialPosition = transform.position; targetIndicator.SetActive(false); // 初始时隐藏目标框 exitZoomButton.gameObject.SetActive(false); // 初始时隐藏退出按钮 exitZoomButton.onClick.AddListener(ExitZoom); } void Update() { if (isZoomedIn) return; // 如果已经缩放,不再更新位置 HandleMouseMovement(); HandleTargetIndicator(); } void HandleMouseMovement() { // 获取鼠标位置 Vector3 mousePosition = Input.mousePosition; Vector3 worldMousePosition = mainCamera.ScreenToWorldPoint(mousePosition); worldMousePosition.z = 0; // 确保 z 为 0 // 计算偏移量并反向 Vector3 offset = (mainCamera.transform.position - worldMousePosition) * parallaxEffectMultiplier; offset.x = Mathf.Clamp(offset.x, -maxOffset.x, maxOffset.x); offset.y = Mathf.Clamp(offset.y, -maxOffset.y, maxOffset.y); // 更新位置 Vector3 targetPosition = initialPosition + offset; transform.DOMove(targetPosition, 0.2f).SetEase(Ease.OutSine); } void HandleTargetIndicator() { // 获取鼠标位置 Vector3 mousePosition = Input.mousePosition; RaycastHit2D hit = Physics2D.Raycast(mainCamera.ScreenToWorldPoint(mousePosition), Vector2.zero); if (hit.collider != null && hit.collider.CompareTag("Target")) // 检查是否是目标 Sprite { targetIndicator.SetActive(true); BoxCollider2D boxCollider = hit.collider.GetComponent(); if (boxCollider != null) { // 获取 BoxCollider2D 的大小和位置 Vector3 boxCenter = boxCollider.bounds.center; Vector3 boxSize = boxCollider.bounds.size; // 转换为屏幕坐标 Vector3 screenCenter = mainCamera.WorldToScreenPoint(boxCenter); Vector2 screenSize = mainCamera.WorldToScreenPoint(boxCenter + boxSize) - mainCamera.WorldToScreenPoint(boxCenter); // 设置目标框位置和大小 RectTransform indicatorRectTransform = targetIndicator.GetComponent(); indicatorRectTransform.position = screenCenter; // 动画效果:先放大再缩小 indicatorRectTransform.localScale = Vector3.one * 1.5f; indicatorRectTransform.DOScale(Vector3.one, 0.2f).SetEase(Ease.OutBounce); indicatorRectTransform.sizeDelta = screenSize; // 设置目标名称 targetNameText.text = hit.collider.name; } // 点击目标框触发缩放 if (Input.GetMouseButtonDown(0)) { currentTarget = hit.collider.transform; ZoomIn(); } } else { targetIndicator.SetActive(false); } } void ZoomIn() { isZoomedIn = true; targetIndicator.SetActive(false); // 隐藏目标框 Vector3 targetPosition = currentTarget.position; targetPosition.z = -10; // 确保 Z 轴位置为 -10 // 防止相机超出场景边界 float cameraHalfHeight = mainCamera.orthographicSize; float cameraHalfWidth = cameraHalfHeight * mainCamera.aspect; targetPosition.x = Mathf.Clamp(targetPosition.x, sceneBoundsMin.x + cameraHalfWidth, sceneBoundsMax.x - cameraHalfWidth); targetPosition.y = Mathf.Clamp(targetPosition.y, sceneBoundsMin.y + cameraHalfHeight, sceneBoundsMax.y - cameraHalfHeight); // 动画效果:缩放相机 mainCamera.transform.DOMove(targetPosition, zoomDuration).SetEase(Ease.OutExpo); // 使用更平滑的缓动 mainCamera.DOOrthoSize(mainCamera.orthographicSize / zoomInScale, zoomDuration).SetEase(Ease.OutExpo).OnComplete(() => { // 缩放结束后显示退出按钮 ShowExitButton(); }); } void ShowExitButton() { // 设置按钮位置在目标上方 Vector3 buttonPosition = currentTarget.position; buttonPosition.z = 0; // 确保 z 为 0 buttonPosition.y += 1.0f; // 根据需要调整按钮的高度 exitZoomButton.transform.position = mainCamera.WorldToScreenPoint(buttonPosition); // 将按钮位置设置为目标上方 exitZoomButton.gameObject.SetActive(true); // 显示退出缩放按钮 } void ExitZoom() { if (!isZoomedIn) return; // 如果没有缩放则直接返回 isZoomedIn = false; targetIndicator.SetActive(false); // 确保在退出缩放时隐藏目标框 exitZoomButton.gameObject.SetActive(false); // 隐藏退出缩放按钮 // 计算目标缩放 float targetOrthoSize = mainCamera.orthographicSize * zoomInScale; // 获取缩放时的目标位置 Vector3 targetPosition = currentTarget.position; targetPosition.z = -10; // 确保 Z 轴位置为 -10 // 确保目标位置在边界内 float cameraHalfHeight = targetOrthoSize; // 使用目标缩放计算边界 float cameraHalfWidth = cameraHalfHeight * mainCamera.aspect; targetPosition.x = Mathf.Clamp(targetPosition.x, sceneBoundsMin.x + cameraHalfWidth, sceneBoundsMax.x - cameraHalfWidth); targetPosition.y = Mathf.Clamp(targetPosition.y, sceneBoundsMin.y + cameraHalfHeight, sceneBoundsMax.y - cameraHalfHeight); // 动画效果:先缩放再移动 Sequence zoomOutSequence = DOTween.Sequence(); zoomOutSequence.Append(mainCamera.DOOrthoSize(targetOrthoSize, zoomDuration).SetEase(Ease.OutExpo)); zoomOutSequence.Join(mainCamera.transform.DOMove(targetPosition, zoomDuration).SetEase(Ease.OutExpo)); } void OnDrawGizmos() { // 设置 Gizmos 颜色 Gizmos.color = Color.red; // 绘制场景边界 Vector3 bottomLeft = new Vector3(sceneBoundsMin.x, sceneBoundsMin.y, 0); Vector3 topRight = new Vector3(sceneBoundsMax.x, sceneBoundsMax.y, 0); // 绘制边界框 Gizmos.DrawLine(bottomLeft, new Vector3(bottomLeft.x, topRight.y, 0)); Gizmos.DrawLine(bottomLeft, new Vector3(topRight.x, bottomLeft.y, 0)); Gizmos.DrawLine(topRight, new Vector3(bottomLeft.x, topRight.y, 0)); Gizmos.DrawLine(topRight, new Vector3(topRight.x, bottomLeft.y, 0)); } }