using Sirenix.OdinInspector; using System.Collections; using System.Collections.Generic; using UnityEngine; /// /// 最上层UI_箭头指引 /// public partial class TopmostLayerUI { /// /// 边缘间隔 /// public float edgeSpacing=0.5f; /// /// 箭头指引节点 /// public Transform arrowheadPointToNode; /// /// 箭头指向的字典 /// public Dictionary arrowPointsDic = new Dictionary(); /// /// 设置箭头指向 /// /// MonoBehaviour类 /// 指向ID /// 指向的3D对象 /// 图标 public void SetArrowObj(string name, GameObject target, Sprite sprite = null) { if (this.arrowPointsDic.ContainsKey(name)) return; YooAssetManager.Instance.LoadAssetAsync(PackagesName.GameData, "ArrowObj", (arrowObj) => { ArrowObjUI arrows =CachePoolManager.Instance.Take(arrowObj).GetComponent(); arrows.SetIconImage(sprite); arrows.transform.SetParent(arrowheadPointToNode); arrows.transform.localPosition = Vector3.zero; arrows.transform.localScale = Vector3.one; Coroutine coroutine = StartCoroutine(E_SetPointObj(arrows, target.transform)); ArrowPoints arrowPoints = new ArrowPoints(); arrowPoints.coroutine = coroutine; arrowPoints.arrowObj = arrows.gameObject; if (!arrowPointsDic.ContainsKey(name)) { arrowPointsDic.Add(name, arrowPoints); } }); } /// /// 设置箭头指向的协程 /// /// private IEnumerator E_SetPointObj(ArrowObjUI arrows, Transform target) { Vector3 recordingPos=Vector3.zero; arrows.gameObject.SetActive(false); while (true) { if (target) { var pos = Camera.main.WorldToScreenPoint(target.transform.position); var distance = Vector3.Distance(recordingPos, pos); if (distance > 1) { recordingPos = pos; if (0 > pos.x || pos.x > Screen.width || pos.y < 0 || pos.y > Screen.height || pos.z < 0) { 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).normalized; //通过反余弦函数获取 向量 a、b 夹角(默认为 弧度) float radians = Mathf.Atan2(dir.y, dir.x); //将弧度转换为 角度 float angle = radians * Mathf.Rad2Deg; arrows.transform.localEulerAngles = new Vector3(0, 0, angle); float sereenangle = (float)Screen.height / (float)Screen.width; var va = System.Math.Abs(dir.y / dir.x); if (va <= sereenangle) { var length = arrows.GetComponent().sizeDelta.x; if (pos.x < 0) { arrows.transform.position = GetNodeX(pos, startpos, length * edgeSpacing); } else { arrows.transform.position = GetNodeX(pos, startpos, Screen.width - length * edgeSpacing); } } else { var length = arrows.GetComponent().sizeDelta.x; if (pos.y < 0) { arrows.transform.position = GetNodeY(pos, startpos, length * edgeSpacing); } else { arrows.transform.position = GetNodeY(pos, startpos, Screen.height - length * edgeSpacing); } } } else { arrows.gameObject.SetActive(false); } } } yield return null; } } /// /// 计算物体超过屏幕高或小于0时UI的位置 /// /// private Vector3 GetNodeY(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; } /// /// 计算物体超过屏幕宽或小于0时UI的位置 /// /// private Vector3 GetNodeX(Vector3 pos, Vector3 startpos, float v) { 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; } /// /// 指定关闭 /// /// public void SpecifyClose(string name) { if (arrowPointsDic.ContainsKey(name)) { StopCoroutine(arrowPointsDic[name].coroutine); Destroy(arrowPointsDic[name].arrowObj); arrowPointsDic.Remove(name); } } /// /// 全部关闭 /// [Button] public void Clear() { foreach (var item in arrowPointsDic) { StopCoroutine(arrowPointsDic[item.Key].coroutine); Destroy(arrowPointsDic[item.Key].arrowObj); } arrowPointsDic.Clear(); } } /// /// 指向对象 /// public class ArrowPoints { /// /// 指向的协程 /// public Coroutine coroutine; /// /// 指向问题的UI /// public GameObject arrowObj; }