2d UI 实时跟随场景3d物体位置,显示 3d 物体头顶信息,看起来像是场景中的3dUI,实质是2d UI
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
using UnityEngine.UI;
/// <summary>
/// 2d UI 实时跟随场景3d物体位置,显示 3d 物体头顶信息,看起来像是场景中的3dUI,实质是2d UI
/// </summary>
public class UIFollow3DGameObject : MonoBehaviour
{
public Vector3 targetPos;
private Camera mainCamera;
private CanvasGroup canvas;
bool _isInCamera = true; //是否在摄像机视野范围内
void Awake()
{
mainCamera = Camera.main;
canvas = GetComponent<CanvasGroup>();
if (canvas == null)
{
canvas = gameObject.AddComponent<CanvasGroup>();
}
_isInCamera = IsInCamera(mainCamera,targetPos);
}
/// <summary>
/// 判断是否在摄像机视野范围内
/// </summary>
/// <returns></returns>
bool IsInCamera(Camera camera,Vector3 pos)
{
//转化为视角坐标
Vector3 viewPos = camera.WorldToViewportPoint(pos);
// z<0代表在相机背后
if (viewPos.z < 0) return false;
//太远了!看不到了!
if (viewPos.z > camera.farClipPlane)
return false;
// x,y取值在 0~1之外时代表在视角范围外;
if (viewPos.x < 0 || viewPos.y < 0 || viewPos.x > 1 || viewPos.y > 1) return false;
return true;
}
void LateUpdate()
{
if (IsInCamera(mainCamera, targetPos) != _isInCamera)
{
Debug.Log("改变是否在视野范围内");
_isInCamera = IsInCamera(mainCamera, targetPos);
MaskableGraphic[] childs = GetComponentsInChildren<MaskableGraphic>();
foreach (var item in childs)
{
item.enabled = _isInCamera;
}
if (_isInCamera == false) return;
}
if (targetPos != null && mainCamera != null)
{
ResetPos();
if (Time.frameCount % 5 == 0)
{
ResetAlpha();
}
}
}
void ResetPos()
{
transform.position = mainCamera.WorldToScreenPoint(targetPos);
}
void ResetAlpha()
{
if (transform.position.z > 0f && canvas.alpha < 0.1f)
{
canvas.alpha = 1f;
}
else if (transform.position.z < 0f && canvas.alpha > 0.9f)
{
canvas.alpha = 0f;
}
}
}