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