Unity 2d UI 实时跟随场景3d物体

发布于:2024-10-15 ⋅ 阅读:(126) ⋅ 点赞:(0)

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

}