当前位置: 首页 > news >正文

Unity实现在3D模型标记

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

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

在这里插入图片描述

代码:

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)){// 创建UIGameObject 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轴位置设置为-150Vector3 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;}
}

相关文章:

Unity实现在3D模型标记

Canvas 模式是UI与3D混合模式&#xff08;Render modelScreen space-Camera) 实现在3D模型标记&#xff0c;旋转跟随是UI不在3D物体下 代码&#xff1a; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public clas…...

iOS开发-NotificationServiceExtension实现实时音视频呼叫通知响铃与震动

iOS开发-NotificationServiceExtension实现实时音视频呼叫通知响铃与震动 在之前的开发中&#xff0c;遇到了实时音视频呼叫通知&#xff0c;当App未打开或者App在后台时候&#xff0c;需要通知到用户&#xff0c;用户点击通知栏后是否接入实时音视频的视频或者音频通话。 在…...

性能调试【学习笔记】

什么是调优&#xff1f; 每执行一个Java命令&#xff0c;就分配一个JVM&#xff0c;调优时不要混淆。 根据需求进行JVM规划和预调优优化运行JVM的运行环境&#xff08;慢、卡顿&#xff09;解决JVM运行过程中出现的各种问题&#xff08;内存泄露、内存溢出OOM&#xff09; 生…...

【taro react】---- 获取元素的位置和宽高等信息

1. 需求分析 添加节点的布局位置的查询请求。相对于显示区域&#xff0c;以像素为单位。其功能类似于 DOM 的 getBoundingClientRect。返回 NodesRef 对应的 SelectorQuery。区分小程序和H5的环境&#xff0c;调用 getBoundingClientRect 获取对应的信息。 2. H5 实现 判断传…...

Java【Spring】项目创建、存储和获取 Bean 的基本方式

文章目录 前言一、创建 Spring 项目1, 创建 Maven 项目2, 添加 Spring 依赖3, 创建启动类 二、存储 Bean 的基本方式1, 创建 Bean2, 存储 Bean 三、获取 Bean 的基本方式1, 获取上下文对象2, 获取 Bean3, 使用 Bean 总结 前言 各位读者好, 我是小陈, 这是我的个人主页, 希望我的…...

docker minio安装

1.介绍 Minio是一款开源的对象存储服务&#xff0c;它可以在任何硬件或云平台上提供高性能、高可用性和高安全性的存储解决方案。Minio最新版是2021年11月发布的RELEASE.2021-11-24T23-19-33Z&#xff0c;它带来了以下几个方面的改进和新特性&#xff1a; - 支持S3 Select AP…...

设计模式-命令模式在Java中的使用示例-桌面程序自定义功能键

场景 欲开发一个桌面版应用程序&#xff0c;该应用程序为用户提供了一系列自定义功能键&#xff0c;用户可以通过这些功能键来实现一些快捷操作。 用户可以将功能键和相应功能绑定在一起&#xff0c;还可以根据需要来修改功能键的设置&#xff0c;而且系统在未来可能还会增加…...

分冶算法 剑指 07 重建二叉树 排序算法:剑指45 把数组排成最小的数 10-I 斐波那契数列

来记录几个注意事项 1.vector容器里利用find&#xff08;&#xff09;函数 不同于map&#xff08;map有find方法&#xff09;&#xff0c;vector本身是没有find这一方法&#xff0c;其find是依靠algorithm来实现的。 所以要包含头文件 #include <iostream> #include <…...

Postgresql取消正在执行的任务或强制终止正在执行的任务

Postgresql取消正在执行的任务或强制终止正在执行的任务 要停止 PostgreSQL 数据库中当前正在执行的所有任务&#xff0c;可以使用以下方法&#xff1a; 使用 pg_cancel_backend 函数&#xff1a;连接到 PostgreSQL 数据库&#xff0c;并执行以下命令以停止所有正在执行的任务…...

【Linux】Centos7 的 Systemctl 与 创建系统服务 (shell脚本)

Systemctl systemctl 命令 # 启动 systemctl start NAME.service # 停止 systemctl stop NAME.service # 重启 systemctl restart NAME.service # 查看状态 systemctl status NAME.service # 查看所有激活系统服务 systemctl list-units -t service # 查看所有系统服务 syste…...

Redis集群Cluster搭建

Redis集群Cluster搭建 集群框架1、下载redis2.创建Cluster文件3.修改redis配置文件4.启动redis5.链接各个redis6.分配槽位7.添加从机节点&#xff08;备份Redis&#xff09;8.以集群方式登录9.使用开源Redis可视化客户端链接 集群框架 三个集群节点&#xff0c;每个节点有个副本…...

swing组件应用

1. 组件概述 &#xff08;1&#xff09; 说明 组件组成Java 的图形界面的各个元素&#xff0c;按照不同的功能&#xff0c;可分为 顶层容器、中间容器、基本组件。顶层容器为java.awt.Window的子类&#xff0c;有JFrame、JDialog等。中间容器和基础组件都为javax.swing.JCompo…...

Spring学习记录----十五、面向切面编程AOP+十六、Spring对事务的支持

十五、面向切面编程AOP IoC使软件组件松耦合。AOP让你能够捕捉系统中经常使用的功能&#xff0c;把它转化成组件。 AOP&#xff08;Aspect Oriented Programming&#xff09;&#xff1a;面向切面编程&#xff0c;面向方面编程。&#xff08;AOP是一种编程技术&#xff09; …...

Color Correction (颜色校正)

介绍 在Unity中&#xff0c;Color Correction (颜色校正) 是一种用于调整场景或游戏画面颜色的技术。其中&#xff0c;Curves&#xff08;曲线&#xff09;和Saturation&#xff08;饱和度&#xff09;是常用的Color Correction工具。通过Curves&#xff0c;可以对RGB通道进行…...

Unity-缓存池

一、.基础缓存池实现 继承的Singleton脚本为 public class Singleton<T> where T : new() {private static T _instance;public static T GetIstance(){if (_instance null)_instance new T();return _instance;} } 1.PoolManager using System.Collections; using S…...

ubuntu samba 配置常见问题

samba配置&#xff1a; sudo vi /etc/samba/smb.conf [xxx 共享文件名] comment share folder browseable yes writable yes guest ok yes path /workdir/code/favarite create mask 0777 directory mask 0777 sudo /etc/init.d/smbd restart 重启smb服务 以上操作…...

vue3.3-TinyMCE:TinyMCE富文本编辑器基础使用

一、TinyMCE官网 GitHub - tinymce/tinymce TinyMCE中文文档中文手册 二、官网介绍 TinyMCE是一款易用、且功能强大的所见即所得的富文本编辑器。同类程序有&#xff1a;UEditor、Kindeditor、Simditor、CKEditor、wangEditor、Suneditor、froala等等。 TinyMCE的优势&…...

基于以太坊+IPFS的去中心化数据交易方法及平台

自己的论文&#xff0c;哎费事 目录 基于以太坊IPFS的去中心化数据交易方法及平台 基于以太坊IPFS的去中心化数据交易方法及平台 摘要&#xff1a; 数据交易过程中存在数据权属不明和数据安全问题。本文开发了一种基于以太坊IPFS的去中心化数据交易方法及平台。方法包括&am…...

NestJS 的 拦截器 学习

拦截器会用到RxJs&#xff0c;所以在学习拦截器之前可以先了解一下它。 拦截器是使用Injectable()装饰器装饰的类并且实现了接口NestInterceptor。 拦截器受到 AOP(面向切面编程)技术的启发&#xff0c;具有如下的功能&#xff1a; 在方法执行之前/之后绑定额外的逻辑转换函…...

Spring AOP 中的代理对象是怎么创建出来的?

文章目录 1. AOP 用法2. 原理分析2.1 doCreateBean2.2 postProcessAfterInitialization2.3 getAdvicesAndAdvisorsForBean2.3.1 findCandidateAdvisors2.3.2 findAdvisorsThatCanApply2.3.3 extendAdvisors 2.4 createProxy 今天和小伙伴们聊一聊 Spring AOP 中的代理对象是怎么…...

别再手动拼URL了!Spring Cloud项目里用OpenFeign调用其他服务,保姆级配置避坑指南

别再手动拼URL了&#xff01;Spring Cloud项目里用OpenFeign调用其他服务&#xff0c;保姆级配置避坑指南 微服务架构下&#xff0c;服务间的HTTP调用是家常便饭。很多开发者还在用RestTemplate手动拼接URL、处理序列化&#xff0c;不仅代码冗长&#xff0c;还容易出错。想象一…...

聚焦18650电池点焊机:新能源产业焊接环节的核心设备

在新能源产业高速发展的当下&#xff0c;18650锂电池凭借其高能量密度、长循环寿命及稳定性能&#xff0c;成为电动汽车、储能系统、便携电子设备等领域的核心动力源。作为电池组装环节的关键设备&#xff0c;18650单节自动点焊机通过精密的焊接技术&#xff0c;将电池极耳与镍…...

零基础入门gstack:借助快马AI生成你的第一个可运行React+TypeScript项目

作为一名刚接触前端开发的新手&#xff0c;第一次听说gstack&#xff08;ViteReactTypeScript组合&#xff09;时&#xff0c;我完全不知道从何入手。直到发现了InsCode(快马)平台&#xff0c;才真正体会到"零配置"开发是什么感觉。下面记录我的学习过程&#xff0c;…...

VisualGDB跨平台调试避坑指南:用VS远程调试Linux程序(2023最新版配置)

VisualGDB跨平台调试实战&#xff1a;2023年VS远程开发Linux程序避坑指南 当Visual Studio开发者首次尝试在Linux环境下进行C开发时&#xff0c;往往会面临调试工具链断裂的困境。传统的gdb命令行调试方式与Windows开发者熟悉的图形化调试体验存在巨大鸿沟&#xff0c;而Visual…...

终极指南:PrivateGPT增量文档处理策略与动态更新解决方案

终极指南&#xff1a;PrivateGPT增量文档处理策略与动态更新解决方案 【免费下载链接】privateGPT 利用GPT的强大功能与你的文档进行互动&#xff0c;确保100%的隐私保护&#xff0c;无数据泄露风险 项目地址: https://gitcode.com/GitHub_Trending/pr/privateGPT Priva…...

如何用QtScrcpy实现低延迟Android投屏?5个技巧带你解锁高效多设备控制体验

如何用QtScrcpy实现低延迟Android投屏&#xff1f;5个技巧带你解锁高效多设备控制体验 【免费下载链接】QtScrcpy Android实时投屏软件&#xff0c;此应用程序提供USB(或通过TCP/IP)连接的Android设备的显示和控制。它不需要任何root访问权限 项目地址: https://gitcode.com/…...

DBShadow横空出世,Dapper.net的天花板盖不住了

一、DBShadow是什么DBShadow是.net开源的高性能ORMDBShadow使用开源项目ShadowSql高效拼接sqlDBShadow使用开源项目PocoEmit.Mapper高效映射查询参数和查询结果也就是说SqlBuilder(ShadowSql)OOM(PocoEmit.Mapper)ORM(DBShadow)二、DBShadow和Dapper对比一下1. Dapper代码await…...

对 OS:TEP 的 MLFQ 策略的一点思考

1.SJF 调度算法SJF 没啥好说的, 书上讲的很清楚了, SJF 就是最短任务优先原则, 其设计初衷是想解决 FIFO 的糟糕的周转时间的问题.但是, 正如书上所说, 这玩意主打一个秩序井然, 只能处理所有任务同时到队列的情况, 要是某堆进程不按这套路出牌, 那 SJF 立马完蛋, 书上就有一个…...

视频高清低延时直播/音视频点播/云点播/云直播EasyDSS在校园教育/K12教育等各场景中的应用介绍

在线教育的核心竞争力&#xff0c;归根结底在于教学体验的优劣&#xff0c;而视频技术作为线上教学的核心载体&#xff0c;直接决定了教学体验的上限。随着在线教育行业的快速迭代&#xff0c;学员对线上课堂的要求愈发严苛&#xff1a;不仅需要高清流畅、稳定无卡顿的音视频传…...

AirPods Pro 3 与 Bose QC Ultra Earbuds 2:无线耳机市场的激烈较量

AirPods Pro 3 与 Bose QC Ultra Earbuds 2&#xff1a;新功能大比拼最新款的 AirPods Pro 3 引入了一系列新功能&#xff0c;提升了音频效果&#xff0c;增强了降噪能力&#xff0c;还具备助听模式、实时翻译、自动切换、空间音频、心率监测等附加功能。而 Bose QuietComfort …...