113 lines
4.4 KiB
C#
113 lines
4.4 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
public class TargetIndicator : MonoBehaviour
|
|
{
|
|
public Camera mainCamera; // 玩家摄像机
|
|
public Transform target; // 目标点
|
|
public RectTransform uiCanvas; // UI Canvas 的 RectTransform
|
|
public RectTransform targetIcon; // 目标图标的 UI
|
|
public Text distanceText; // 屏幕内显示的距离文本
|
|
public RectTransform arrowIcon; // 屏幕外箭头图标
|
|
public Text arrowDistanceText; // 屏幕外箭头后面的距离文本
|
|
|
|
public float edgePadding = 50f; // 箭头距离屏幕边缘的间距
|
|
public Vector2 textOffset = new Vector2(0, -30); // 文本相对箭头的偏移
|
|
|
|
void Update()
|
|
{
|
|
// 将目标点从世界坐标转换到屏幕坐标
|
|
Vector3 screenPoint = mainCamera.WorldToScreenPoint(target.position);
|
|
|
|
// 检查目标是否在屏幕内
|
|
if (screenPoint.z > 0 && screenPoint.x > 0 && screenPoint.x < Screen.width && screenPoint.y > 0 && screenPoint.y < Screen.height)
|
|
{
|
|
// 目标在屏幕内,显示目标图标
|
|
targetIcon.gameObject.SetActive(true);
|
|
arrowIcon.gameObject.SetActive(false); // 隐藏箭头
|
|
arrowDistanceText.gameObject.SetActive(false); // 隐藏箭头距离文本
|
|
|
|
// 更新图标位置
|
|
targetIcon.position = screenPoint;
|
|
|
|
// 更新屏幕内距离文本
|
|
float distance = Vector3.Distance(mainCamera.transform.position, target.position);
|
|
distanceText.text = $"{distance:F1}m";
|
|
}
|
|
else
|
|
{
|
|
// 目标在屏幕外,显示箭头
|
|
targetIcon.gameObject.SetActive(false);
|
|
arrowIcon.gameObject.SetActive(true); // 显示箭头
|
|
arrowDistanceText.gameObject.SetActive(true); // 显示箭头距离文本
|
|
|
|
// 如果目标在玩家后方,翻转方向
|
|
if (screenPoint.z < 0)
|
|
{
|
|
screenPoint.x = Screen.width - screenPoint.x; // 水平翻转
|
|
screenPoint.y = Screen.height - screenPoint.y; // 垂直翻转
|
|
}
|
|
|
|
// 计算目标点相对于屏幕中心的方向
|
|
Vector3 direction = (screenPoint - new Vector3(Screen.width / 2, Screen.height / 2, 0)).normalized;
|
|
|
|
// 计算箭头在屏幕边界的位置
|
|
Vector3 edgePosition = GetScreenEdgePosition(direction);
|
|
|
|
// 设置箭头位置
|
|
arrowIcon.position = edgePosition;
|
|
|
|
// 设置距离文本位置(在箭头下方或后面)
|
|
Vector3 textPosition = edgePosition + (Vector3)textOffset;
|
|
textPosition = ClampToScreenBounds(textPosition); // 限制文本在屏幕范围内
|
|
arrowDistanceText.transform.position = textPosition;
|
|
|
|
// 保持距离文本水平显示
|
|
arrowDistanceText.transform.rotation = Quaternion.identity;
|
|
|
|
// 更新距离文本内容
|
|
float distance = Vector3.Distance(mainCamera.transform.position, target.position);
|
|
arrowDistanceText.text = $"{distance:F1}m";
|
|
|
|
// 旋转箭头使其指向目标方向
|
|
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
|
|
arrowIcon.rotation = Quaternion.Euler(0, 0, angle);
|
|
}
|
|
}
|
|
|
|
// 计算箭头在屏幕边界的位置
|
|
private Vector3 GetScreenEdgePosition(Vector3 direction)
|
|
{
|
|
// 计算屏幕宽高
|
|
float halfScreenWidth = Screen.width / 2 - edgePadding;
|
|
float halfScreenHeight = Screen.height / 2 - edgePadding;
|
|
|
|
// 判断箭头是否应该在屏幕的上下边缘
|
|
float slope = direction.y / direction.x;
|
|
if (Mathf.Abs(slope) > halfScreenHeight / halfScreenWidth)
|
|
{
|
|
// 在上下边缘
|
|
float edgeY = Mathf.Sign(direction.y) * halfScreenHeight + Screen.height / 2;
|
|
float edgeX = (edgeY - Screen.height / 2) / slope + Screen.width / 2;
|
|
return new Vector3(edgeX, edgeY, 0);
|
|
}
|
|
else
|
|
{
|
|
// 在左右边缘
|
|
float edgeX = Mathf.Sign(direction.x) * halfScreenWidth + Screen.width / 2;
|
|
float edgeY = slope * (edgeX - Screen.width / 2) + Screen.height / 2;
|
|
return new Vector3(edgeX, edgeY, 0);
|
|
}
|
|
}
|
|
|
|
// 限制文本在屏幕范围内
|
|
private Vector3 ClampToScreenBounds(Vector3 position)
|
|
{
|
|
position.x = Mathf.Clamp(position.x, edgePadding, Screen.width - edgePadding);
|
|
position.y = Mathf.Clamp(position.y, edgePadding, Screen.height - edgePadding);
|
|
return position;
|
|
}
|
|
}
|