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; } }