【Unity】实现箭头追踪效果,将2D箭头沿着屏幕边缘指向3D模型

只需要一个脚本,就可以例图的效果


在这里插入图片描述
废话不多说,直接上脚本(此脚本只支持单个箭头追踪,如果需要实现多箭头追踪的效果,请自己酌情修改脚本,或者多调用几次这个方法)

using System.Collections;
using UnityEngine;

public class UIGuidManager : MonoBehaviour
{
    public Transform arrows; //2d的箭头拖在这里
    Transform target;
    Vector3 prePos = Vector3.zero;
    //这个是检测间隔,和性能挂钩,默认为0.2,自己可以随更改
    public float checkTime = 0.2f;

//被指向的3D对象传入这里,在全局的任何地方,调用一次这个方法即可
    public void SetGuid(Transform _target)
    {
        target = _target;
    }
    void Start()
    {
        arrows.gameObject.SetActive(false);
        StartCoroutine(TrakerGuider());
    }

    private IEnumerator TrakerGuider()
    {
        while (true)
        {
            yield return new WaitForSeconds(checkTime);
            SetGuid();
        }
    }

    private void SetGuid()
    {
        if (target)
        {
            var pos = Camera.main.WorldToScreenPoint(target.transform.position);
            Debug.Log("pos:" + pos);
            var distance = Vector3.Distance(prePos, pos);
            if (distance < 1) { Debug.Log("没动"); return; };
            prePos = pos;
            if (0 < pos.x && pos.x < Screen.width && pos.y > 0 && pos.y < Screen.height && pos.z > 0)
            {
                arrows.gameObject.SetActive(false);
                return;
            }
            else
                arrows.gameObject.SetActive(true);
            if (pos.z < 0)
                pos = pos * -1;
            var startpos = new Vector3(Screen.width / 2f, Screen.height / 2f, 0);
            var dir = pos - startpos;

            //通过反余弦函数获取 向量 a、b 夹角(默认为 弧度)
            float radians = Mathf.Atan2(dir.y, dir.x);

            //将弧度转换为 角度
            float angle = radians * Mathf.Rad2Deg;
            Debug.Log("angle:" + angle);
            arrows.localEulerAngles = new Vector3(0, 0, angle);
            // arrows.transform.LookAt(new Vector3(pos.x, pos.y, 0));
            float sereenangle = (float)Screen.height / (float)Screen.width;
            var va = System.Math.Abs(dir.y / dir.x);
            if (va <= sereenangle)
            {
                var length = arrows.GetComponent<RectTransform>().sizeDelta.x;
                if (pos.x < 0)
                    arrows.transform.position = GetNode(pos, startpos, length * 0.5f);
                else
                    arrows.transform.position = GetNode(pos, startpos, Screen.width - length * 0.5f);
            }
            else
            {
                var length = arrows.GetComponent<RectTransform>().sizeDelta.x;

                if (pos.y < 0)
                    arrows.transform.position = GetNode2(pos, startpos, length * 0.5f);
                else
                    arrows.transform.position = GetNode2(pos, startpos, Screen.height - length * 0.5f);
            }
        }
    }

    private Vector3 GetNode2(Vector3 pos, Vector3 startpos, float v)
    {
        pos = new Vector3(pos.x, pos.y, 0);
        Vector3 ab = pos - startpos;
        Vector3 am = ab * (Mathf.Abs(startpos.y - v) / Mathf.Abs(pos.y - startpos.y));
        Vector3 om = startpos + am;
        return om;
    }

    private Vector3 GetNode(Vector3 pos, Vector3 startpos, float v)
    {
        //float high = ((startpos.x - length) * (pos.y - startpos.y) / (startpos.x - pos.x)) + startpos.y;
        //return new Vector3(length, high, 0);
        pos = new Vector3(pos.x, pos.y, 0);
        Vector3 ab = pos - startpos;
        Vector3 am = ab * (Mathf.Abs(startpos.x - v) / Mathf.Abs(pos.x - startpos.x));
        Vector3 om = startpos + am;
        return om;
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章