|
|
|
@@ -0,0 +1,182 @@
|
|
|
|
|
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<BoxCollider2D>();
|
|
|
|
|
|
|
|
|
|
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<RectTransform>();
|
|
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
}
|