_xiaofang/xiaofang/Assets/Script/hylScripts/TargetIndicator.cs
2024-12-19 17:14:14 +08:00

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