Unity中实现超出屏幕的敌人/队友位置显示_# Unity相关技术

using UnityEngine;
using UnityEngine.UI;

public class Test : MonoBehaviour
{
    public GameObject go;//物体
    public GameObject targetGo;//目标物体

    public Image labelUI_img;//标记UI的Image组件

    private float labelUI_HalfWidth;//标记UI一半的宽
    private float labelUI_HalfHeight;//标记UI一半的高
    private Vector2 v3;//v3的坐标
    private Vector2 v4;//v4的坐标

    private void Awake()
    {
        labelUI_HalfWidth = labelUI_img.GetComponent<RectTransform>().rect.width / 2;
        labelUI_HalfHeight = labelUI_img.GetComponent<RectTransform>().rect.height / 2;
    }

    private void Update()
    {
        //判断标记UI的显示与隐藏
        if (IsInView(targetGo.transform.position))
        {
            labelUI_img.enabled = false;
        }
        else
        {
            labelUI_img.enabled = true;
        }

        //设置标记UI的显示位置
        GetV3AndV4(out v3, out v4);
        labelUI_img.transform.localPosition = CalculateCrossPoint(go.transform.position, targetGo.transform.position, v3, v4);
    }

    /// <summary>
    /// 得到v3,v4的值
    /// </summary>
    private void GetV3AndV4(out Vector2 v3, out Vector2 v4)
    {
        Vector2 v1 = Camera.main.WorldToScreenPoint(go.transform.position);
        Vector2 v2 = Camera.main.WorldToScreenPoint(targetGo.transform.position);
        Vector2 offset = v2 - v1;
        if (Mathf.Abs(offset.x) > Mathf.Abs(offset.y))
        {
            if (offset.x > 0)
            {
                v3 = new Vector2(Screen.width - labelUI_HalfWidth, 0);
                v4 = new Vector2(Screen.width - labelUI_HalfWidth, Screen.height);
                labelUI_img.transform.rotation = Quaternion.Euler(0, 0, -135);
            }
            else
            {
                v3 = new Vector2(0 + labelUI_HalfWidth, 0);
                v4 = new Vector2(0 + labelUI_HalfWidth, Screen.height);
                labelUI_img.transform.rotation = Quaternion.Euler(0, 0, 45);
            }
        }
        else
        {
            if (offset.y > 0)
            {
                v3 = new Vector2(0, Screen.height - labelUI_HalfHeight);
                v4 = new Vector2(Screen.width, Screen.height - labelUI_HalfHeight);
                labelUI_img.transform.rotation = Quaternion.Euler(0, 0, -40);
            }
            else
            {
                v3 = new Vector2(0, 0 + labelUI_HalfHeight);
                v4 = new Vector2(Screen.width, 0 + labelUI_HalfHeight);
                labelUI_img.transform.rotation = Quaternion.Euler(0, 0, -220);
            }
        }
    }

    /// <summary>
    /// 给定四个点,求两条线段的交点(y=a1x+b1,y=a2x+b2)
    /// v1,v2是物体与目标物体的位置,v3,v4是屏幕左上,左下,右上,右下中的两个点
    /// </summary>
    private Vector2 CalculateCrossPoint(Vector3 v1, Vector3 v2, Vector2 v3, Vector2 v4)
    {
        v1 = Camera.main.WorldToScreenPoint(v1);
        v2 = Camera.main.WorldToScreenPoint(v2);

        float a1 = 0, b1 = 0, a2 = 0, b2 = 0;
        Vector2 crossPoint = Vector2.zero;

        if (v1.x != v2.x)
        {
            a1 = (v1.y - v2.y) / (v1.x - v2.x);
        }
        if (v1.y != v2.y)
        {
            b1 = v1.y - v1.x * (v1.y - v2.y) / (v1.x - v2.x);
        }

        if (v3.x != v4.x)
        {
            a2 = (v3.y - v4.y) / (v3.x - v4.x);
        }
        if (v3.y != v4.y)
        {
            b2 = v3.y - v3.x * (v3.y - v4.y) / (v3.x - v4.x);
        }

        if (a1 == a2 && b1 == b2)
        {
            Debug.LogWarning("两条线共线,没有交点");
            return Vector2.zero;
        }
        else if (a1 == a2)
        {
            Debug.LogWarning("两条线平行,没有交点");
            return Vector2.zero;
        }
        else
        {
            //交点的x和y坐标
            //(v3与v4需要进行特殊判定处理)
            float x = 0;
            float y = 0;
            if (v3.x == v4.x)
            {
                if (v3.x == 0)
                {
                    x = 0;
                    y = b1;
                }
                else
                {
                    x = v3.x;
                    y = x * a1 + b1;
                }
            }
            else if (v3.y == v4.y)
            {
                if (v3.y == 0)
                {
                    y = 0;
                    x = -b1 / a1;
                }
                else
                {
                    y = v3.y;
                    x = (y - b1) / a1;
                }
            }
            else
            {
                x = (b2 - b1) / (a1 - a2);
                y = a1 * (b2 - b1) / (a1 - a2) + b1;
            }

            //限定x和y的范围
            x = Mathf.Clamp(x, 0, Screen.width);
            y = Mathf.Clamp(y, 0, Screen.height);

            crossPoint = new Vector2(x, y);
            RectTransformUtility.ScreenPointToLocalPointInRectangle(GameObject.Find("Canvas").GetComponent<RectTransform>(),
                crossPoint, null, out crossPoint);
            return crossPoint;
        }
    }

    /// <summary>
    /// 是否在指定相机的视野范围内
    /// </summary>
    /// <param name="worldPos">物体世界坐标</param>
    /// <returns>是否在相机视野范围内</returns>
    public bool IsInView(Vector3 worldPos)
    {
        Transform camTransform = Camera.main.transform;
        Vector2 viewPos = Camera.main.WorldToViewportPoint(worldPos);

        //判断物体是否在相机前面  
        Vector3 dir = (worldPos - camTransform.position).normalized;
        float dot = Vector3.Dot(camTransform.forward, dir);

        if (dot > 0 && viewPos.x >= 0 && viewPos.x <= 1 && viewPos.y >= 0 && viewPos.y <= 1)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}