OvertakingLegend/Assets/UIFrameWork/Script/TopmostLayerUI/TopmostLayerUI_ArrowPoints.cs

201 lines
6.6 KiB
C#

using Sirenix.OdinInspector;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 最上层UI_箭头指引
/// </summary>
public partial class TopmostLayerUI
{
/// <summary>
/// 边缘间隔
/// </summary>
public float edgeSpacing=0.5f;
/// <summary>
/// 箭头指引节点
/// </summary>
public Transform arrowheadPointToNode;
/// <summary>
/// 箭头指向的字典
/// </summary>
public Dictionary<string, ArrowPoints> arrowPointsDic = new Dictionary<string, ArrowPoints>();
/// <summary>
/// 设置箭头指向
/// </summary>
/// <param name="mono">MonoBehaviour类</param>
/// <param name="name">指向ID</param>
/// <param name="target">指向的3D对象</param>
/// <param name="sprite">图标</param>
public void SetArrowObj(string name, GameObject target, Sprite sprite = null)
{
if (this.arrowPointsDic.ContainsKey(name)) return;
YooAssetManager.Instance.LoadAssetAsync<GameObject>(PackagesName.GameData, "ArrowObj", (arrowObj) =>
{
ArrowObjUI arrows =CachePoolManager.Instance.Take(arrowObj).GetComponent<ArrowObjUI>();
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);
}
});
}
/// <summary>
/// 设置箭头指向的协程
/// </summary>
/// <returns></returns>
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<RectTransform>().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<RectTransform>().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;
}
}
/// <summary>
/// 计算物体超过屏幕高或小于0时UI的位置
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// 计算物体超过屏幕宽或小于0时UI的位置
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// 指定关闭
/// </summary>
/// <param name="name"></param>
public void SpecifyClose(string name)
{
if (arrowPointsDic.ContainsKey(name))
{
StopCoroutine(arrowPointsDic[name].coroutine);
Destroy(arrowPointsDic[name].arrowObj);
arrowPointsDic.Remove(name);
}
}
/// <summary>
/// 全部关闭
/// </summary>
[Button]
public void Clear()
{
foreach (var item in arrowPointsDic)
{
StopCoroutine(arrowPointsDic[item.Key].coroutine);
Destroy(arrowPointsDic[item.Key].arrowObj);
}
arrowPointsDic.Clear();
}
}
/// <summary>
/// 指向对象
/// </summary>
public class ArrowPoints
{
/// <summary>
/// 指向的协程
/// </summary>
public Coroutine coroutine;
/// <summary>
/// 指向问题的UI
/// </summary>
public GameObject arrowObj;
}