Unity实现在3D模型标记

Canvas 模式是UI与3D混合模式(Render model=Screen space-Camera)

实现在3D模型标记,旋转跟随是UI不在3D物体下

代码:

csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ClickHandler : MonoBehaviour
{
    public Transform object3D; // 总体模型
    public GameObject imgUIPrefab;
    public Canvas canvas;
    public float fadeSpeed = 2.0f; // 淡入淡出的速度
    private bool isRotating = false;
    private GameObject clickedObject;
    private Vector3 lastMousePosition;
    private Vector3 delta;
    private Dictionary<GameObject, GameObject> generatedUIs = new Dictionary<GameObject, GameObject>();

    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            lastMousePosition = Input.mousePosition;
            isRotating = true;
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;

            if (Physics.Raycast(ray, out hit))
            {
                clickedObject = hit.collider.gameObject;
                // 检查是否为小模型
                if (clickedObject.CompareTag("Model"))
                {
                    isRotating = false;
                    if (!HasGeneratedUI(clickedObject.name))
                    {
                        // 创建UI
                        GameObject imgUI = CreateUIForModel(clickedObject);
                        if (imgUI != null)
                        {
                            // 添加到字典中
                            generatedUIs.Add(imgUI, clickedObject);
                        }
                    }
                }
            }
            UpdateImgUIPosition();
        }

        if (Input.GetMouseButtonUp(0))
        {
            isRotating = false;
        }

        if (isRotating)
        {
            delta = Input.mousePosition - lastMousePosition;
            float rotationSpeed = 0.5f;
            object3D.Rotate(Vector3.up, delta.x * -rotationSpeed, Space.World);
            UpdateImgUIPosition();
        }

        lastMousePosition = Input.mousePosition;
    }

    private GameObject CreateUIForModel(GameObject model)
    {
        // 获取被点击物体的中心点位置
        Vector3 modelCenter = model.transform.position;

        // 将模型的世界坐标转换为屏幕坐标
        Vector3 screenPoint = Camera.main.WorldToScreenPoint(modelCenter);

        // 将屏幕坐标转换为Canvas内的局部坐标
        RectTransform canvasRect = canvas.GetComponent<RectTransform>();
        Vector2 canvasLocalPoint;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRect, screenPoint, Camera.main, out canvasLocalPoint);

        // 设置预制体的位置为Canvas内的局部坐标,将Z轴位置设置为-150
        Vector3 prefabPosition = new Vector3(canvasLocalPoint.x, canvasLocalPoint.y,-150f);

        // 实例化Img UI预制件,并设置其位置为转换后的局部坐标
        GameObject imgUI = Instantiate(imgUIPrefab, prefabPosition, Quaternion.identity);
        imgUI.name = model.name; // 生成UI名字为3D模型名字
        imgUI.transform.SetParent(canvas.transform, false); // 设置Img UI的父对象为Canvas,确保其显示在屏幕上

        return imgUI;
    }

    private void UpdateImgUIPosition()
    {
        foreach (var uiEntry in generatedUIs)
        {
            GameObject ui = uiEntry.Key;
            GameObject matchedModel = uiEntry.Value;

            bool isOccluded = IsObjectOccluded(matchedModel);


            // ui.SetActive(!isOccluded);  // 如果模型被遮挡,则隐藏UI;否则显示UI

            // 如果模型被遮挡,则UI淡出 否则淡入
            Image uiImage = ui.GetComponent<Image>();
            Color color = uiImage.color;
            float targetAlpha = isOccluded ? 0.0f : 1.0f;
            color.a = Mathf.MoveTowards(color.a, targetAlpha, Time.deltaTime * fadeSpeed);
            uiImage.color = color;

            if (!isOccluded)
            {
                // 获取匹配模型的中心点位置
                Vector3 modelCenter = matchedModel.transform.position;

                // 将模型的世界坐标转换为屏幕坐标
                Vector3 screenPoint = Camera.main.WorldToScreenPoint(modelCenter);

                // 将屏幕坐标转换为Canvas内的局部坐标
                RectTransform canvasRect = canvas.GetComponent<RectTransform>();
                Vector2 canvasLocalPoint;
                RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRect, screenPoint, Camera.main, out canvasLocalPoint);
                Vector3 prefabPosition = new Vector3(canvasLocalPoint.x, canvasLocalPoint.y, -150f);

                // 更新UI的位置
                ui.GetComponent<RectTransform>().anchoredPosition = prefabPosition;
            }
        }
    }

    private bool HasGeneratedUI(string name)
    {
        foreach (var ui in generatedUIs.Keys)
        {
            if (ui.name == name)
            {
                return true;
            }
        }
        return false;
    }

    private bool IsObjectOccluded(GameObject obj)
    {
        // 获取摄像机到物体的方向
        Vector3 directionToTarget = obj.transform.position - Camera.main.transform.position;

        // 发射射线
        Ray ray = new Ray(Camera.main.transform.position, directionToTarget);
        RaycastHit hit;

        // 射线检测是否有其他碰撞器位于射线路径上
        if (Physics.Raycast(ray, out hit, directionToTarget.magnitude))
        {
            // 如果射线击中的物体不是目标物体,则表示目标物体被遮挡
            if (hit.collider.gameObject != obj)
            {
                return true;
            }
        }

        return false;
    }
}
相关推荐
异次元的归来10 小时前
Unity DOTS中的share component
unity·游戏引擎
向宇it14 小时前
【从零开始入门unity游戏开发之——C#篇25】C#面向对象动态多态——virtual、override 和 base 关键字、抽象类和抽象方法
java·开发语言·unity·c#·游戏引擎
_oP_i15 小时前
unity webgl部署到iis报错
unity
Go_Accepted15 小时前
Unity全局雾效
unity
向宇it15 小时前
【从零开始入门unity游戏开发之——C#篇24】C#面向对象继承——万物之父(object)、装箱和拆箱、sealed 密封类
java·开发语言·unity·c#·游戏引擎
mirrornan16 小时前
3D和AR技术在电商行业的应用有哪些?
3d·ar·3d建模·3d模型·三维建模
每日出拳老爷子18 小时前
【图形渲染】【Unity Shader】【Nvidia CG】有用的参考资料链接
unity·游戏引擎·图形渲染
工业3D_大熊18 小时前
3D开发工具HOOPS助力造船业加速设计与数字化转型
3d
zaf赵18 小时前
3D 高斯溅射 (Gaussian Splatting)技术,一种实现超写实、高效渲染的突破性技术
3d
北海651619 小时前
Dots 常用操作
unity