278 lines
6.9 KiB
C#

using System;
using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.UI;
using DG.Tweening;
/// 提示UI挂载
// [AddComponentMenu("JiaSuQi/UI/Control/UI Follow Target")]
[RequireComponent(typeof(RectTransform))]
public sealed class UIFollowTarget : MonoBehaviour
{
public Transform Target
{
get { return this.target; }
set { this.target = value; }
}
public Canvas Canvas
{
get { return this.canvas; }
set { this.canvas = value; }
}
public Camera Camera
{
get { return this.gameCamera; }
set { this.gameCamera = value; }
}
/// <summary>
/// 计算屏幕的位置
/// </summary>
public static Vector3 CalculateScreenPosition(Vector3 position/* 目标点*/, Camera camera, Canvas canvas,
RectTransform transform)
{
Assert.IsNotNull<Camera>(camera);
Assert.IsNotNull<Canvas>(canvas);
Assert.IsNotNull<RectTransform>(transform);
//世界坐标转屏幕坐标
Vector3 vector = camera.WorldToScreenPoint(position);
Vector3 zero = Vector3.zero;
//判断canvas 渲染模式
switch (canvas.renderMode)
{
//屏幕空间
case RenderMode.ScreenSpaceOverlay:
RectTransformUtility.ScreenPointToWorldPointInRectangle(transform, vector, null, out zero);
break;
case RenderMode.ScreenSpaceCamera:
//世界空间
case RenderMode.WorldSpace:
RectTransformUtility.ScreenPointToWorldPointInRectangle(transform, vector, canvas.worldCamera,
out zero);
break;
}
return zero;
}
private void Awake()
{
//获取父物体rectTransForm
this.rectTransform = base.GetComponent<RectTransform>();
if (this.gameCamera == null)
{
this.gameCamera = Camera.main;
}
this.UpdatePos();
}
/// <summary>
/// 主要调用方法
/// </summary>
private void LateUpdate()
{
if (this.gameCamera == null)
{
this.gameCamera = Camera.main;
}
UpdatePos();
}
private Tween Anim;
/// <summary>
/// 外部调用方法
/// </summary>
/// <param name="isT"> 是否显示</param>
/// <param name="LiJiWanCheng">是否立即完成</param>
public void PlayShowOrClose(bool isT,bool LiJiWanCheng)
{
if (isT)
{
if (LiJiWanCheng)
{
transform.gameObject.SetActive(true);
YuanDian.color = new Color(1,1,1,1);
zhiyinxian.fillAmount = 1;
tip.transform.localScale=Vector3.one;
}
else
{
transform.gameObject.SetActive(true);
YuanDian.color = new Color(1,1,1,0);
zhiyinxian.fillAmount = 0;
tip.transform.localScale=Vector3.zero;
Anim?.Kill();
Anim = showAnim().Play();
}
}
else
{
if (LiJiWanCheng)
{
YuanDian.color = new Color(1,1,1,0);
zhiyinxian.fillAmount = 0;
tip.transform.localScale=Vector3.zero;
Anim.Kill();
transform.gameObject.SetActive(false);
}
else
{
// Debug.Log("UI关闭动画播放中");
YuanDian.color = new Color(1,1,1,1);
zhiyinxian.fillAmount = 1;
tip.transform.localScale=Vector3.one;
Anim?.Kill();
Anim = close().Play().
OnComplete(() =>
{
transform.gameObject.SetActive(false);
// Debug.Log("UI关闭动画播放完成");
});
}
}
}
/// UI显示动画
/// </summary>
/// <returns></returns>
Tween showAnim()
{
var sequence= DOTween.Sequence();
var t= YuanDian.DOFade(1, 1.25f);
sequence.Insert(0.0f, t);
var t1 = zhiyinxian.DOFillAmount(1,ZhiYinXianTime); sequence.Insert(0.2f, t);
var t2 = tip.transform.DOScale(Vector3.one, TipTime);
sequence.Insert(0.5f, t);
return sequence;
}
/// <summary>
/// UI隐藏动画
/// </summary>
/// <returns></returns>
private Tween close()
{
var sequence = DOTween.Sequence();
Tween t;
t = tip.transform.DOScale(Vector3.zero, 0.2f);
sequence.Insert(0, t);
t = zhiyinxian.DOFillAmount(0, 0.5f);
sequence.Insert(0.5f, t);
t = YuanDian.DOFade(0, 1f);
sequence.Insert(0.85f, t);
return sequence;
}
private void UpdatePos()
{
if (this.target == null || this.canvas == null || this.gameCamera == null || this.rectTransform == null)
{
return;
}
//计算屏幕坐标
Vector3 position = CalculateScreenPosition(this.target.position, this.gameCamera,
this.canvas,tip.GetComponent<RectTransform>() );
tip.transform.position = position+tipOffset;
YuanDian.transform.position = Camera.WorldToScreenPoint(target.position)+YuanDianOffset;
zhiyinxian.transform.position = (YuanDian.transform.position+tip.transform.position)/2;
zhiyinxian.transform.localEulerAngles = new Vector3(0, 0, Vector2.SignedAngle(Vector2.right, YuanDian.transform.position- tip.transform.position));
float length = (YuanDian.transform.position-tip.transform.position).magnitude;
//设置线的宽度 长度
zhiyinxian. GetComponent<RectTransform>().sizeDelta = new Vector2(length, 3f);
}
[SerializeField,Header("image")]
public Image YuanDian;
[SerializeField, Header("原点偏移量")]
private Vector3 YuanDianOffset;
[SerializeField, Header("tip")]
private GameObject tip;
[SerializeField, Header("提示缩放时间")]
private float TipTime;
[SerializeField] private Transform target;
[SerializeField] private Camera gameCamera;
[SerializeField] private Canvas canvas;
[SerializeField, Header("指引线UI")]
private Image zhiyinxian;
[SerializeField, Header("指引线填充时间")]
private float ZhiYinXianTime;
[SerializeField,Header("tip偏移量")]
public Vector3 tipOffset;
[SerializeField, Header("text")]
public Text Text;
private RectTransform rectTransform;
}