unity 模型显示在UI上 并交互(点击、旋转、缩放)

news2025/2/26 22:37:27

1.在Assets创建 Render Texture(下面会用到),根据需要设置Size

2.创建UIRawImage,并把Render Texture赋上

 3.创建相机,如下图:

4.基本UI的准备工作完成,剩下的就是代码了,值得一提:相机我不喜欢单独拿出去管理,就和UI一起就好。如图:

 5.相机控制,直接上代码(添加了一个判断,鼠标必须在rawImage上,其他UI上无效):

/**********************************************************************
 文件信息
 文件名(File Name):                CameraController.cs
 作者(Author):                      TianWenQuan
 创建时间(CreateTime):             #CREATETIME#
 Unity版本(UnityVersion):         #UNITYVERSION#
 项目:
 **********************************************************************/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
namespace Twq
{
    /// <summary>
    /// 该脚本需要挂在摄像机上
    /// </summary>
    public class CameraController : MonoBehaviour
    {
        public Transform targetObject;
        public Vector3 targetOffset;
        public float averageDistance = 5.0f;//初始位置 镜头远近
        public float maxDistance = 20;
        public float minDistance = .6f;
        public float xSpeed = 200.0f;
        public float ySpeed = 200.0f;
        public int yMinLimit = -80;
        public int yMaxLimit = 80;

        public int xMinLimit = -80;
        public int xMaxLimit = 80;

        public int zoomSpeed = 40;
        public float panSpeed = 0.3f;
        public float zoomDampening = 5.0f;
        public float rotateOnOff = 1;

        private float xDeg = 0.0f;
        private float yDeg = 0.0f;
        private float currentDistance;
        private float desiredDistance;
        private Quaternion currentRotation;
        private Quaternion desiredRotation;
        private Quaternion rotation;
        private Vector3 position;
        private float idleTimer = 0.0f;
        private float idleSmooth = 0.0f;

        void Start() { Init(); }
        void OnEnable() { Init(); }

        public void Init()
        {
            tt();
        }
        public void tt()
        {
            if (!targetObject)
            {
                GameObject go = new GameObject("Cam Target");
                go.transform.position = transform.position + (transform.forward * averageDistance);
                targetObject = go.transform;
            }

            currentDistance = averageDistance;
            desiredDistance = averageDistance;

            position = transform.position;
            rotation = transform.rotation;
            currentRotation = transform.rotation;
            desiredRotation = transform.rotation;

            xDeg = Vector3.Angle(Vector3.right, transform.right);
            yDeg = Vector3.Angle(Vector3.up, transform.up);
            position = targetObject.position - (rotation * Vector3.forward * currentDistance + targetOffset);
        }
        void LateUpdate()
        {
            if (IsPointerOverGameObject(Input.mousePosition))
            {
                if (Input.GetMouseButton(2) && Input.GetKey(KeyCode.LeftAlt) && Input.GetKey(KeyCode.LeftControl))
                {
                    desiredDistance -= Input.GetAxis("Mouse Y") * 0.02f * zoomSpeed * 0.125f * Mathf.Abs(desiredDistance);
                }
                else if (Input.GetMouseButton(0))
                {
                    xDeg += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
                    yDeg -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
                    yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);
                    xDeg = ClampAngle(xDeg, xMinLimit, xMaxLimit);


                    desiredRotation = Quaternion.Euler(yDeg, xDeg, 0);
                    currentRotation = transform.rotation;
                    rotation = Quaternion.Lerp(currentRotation, desiredRotation, 0.02f * zoomDampening);
                    transform.rotation = rotation;
                    idleTimer = 0;
                    idleSmooth = 0;

                }
                else
                {
                    //自动旋转

                    //idleTimer += 0.02f;
                    //if (idleTimer > rotateOnOff && rotateOnOff > 0)
                    //{
                    //    idleSmooth += (0.02f + idleSmooth) * 0.005f;
                    //    idleSmooth = Mathf.Clamp(idleSmooth, 0, 1);
                    //    xDeg += xSpeed * 0.001f * idleSmooth;
                    //}

                    //yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);
                    //desiredRotation = Quaternion.Euler(yDeg, xDeg, 0);
                    //currentRotation = transform.rotation;
                    //rotation = Quaternion.Lerp(currentRotation, desiredRotation, 0.02f * zoomDampening * 2);
                    //transform.rotation = rotation;
                }

                desiredDistance -= Input.GetAxis("Mouse ScrollWheel") * 0.02f * zoomSpeed * Mathf.Abs(desiredDistance);
                desiredDistance = Mathf.Clamp(desiredDistance, minDistance, maxDistance);
                currentDistance = Mathf.Lerp(currentDistance, desiredDistance, 0.02f * zoomDampening);
                position = targetObject.position - (rotation * Vector3.forward * currentDistance + targetOffset);
                transform.position = position;
            }
        }
            

        private static float ClampAngle(float angle, float min, float max)
        {
            if (angle < -360)
                angle += 360;
            if (angle > 360)
                angle -= 360;
            return Mathf.Clamp(angle, min, max);
        }
        /// <summary>
        /// 检测是否点击UI
        /// </summary>
        /// <param name="mousePosition">鼠标位置</param>
        /// <returns></returns>
        private bool IsPointerOverGameObject(Vector2 mousePosition)
        {
            //创建一个点击事件
            PointerEventData eventData = new PointerEventData(EventSystem.current);
            eventData.position = mousePosition;
            List<RaycastResult> raycastResults = new List<RaycastResult>();
            //向点击位置发射一条射线,检测是否点击UI
            EventSystem.current.RaycastAll(eventData, raycastResults);

            if (raycastResults.Count > 0)
            {
               // Debug.Log("raycastResults[0].gameObject.name="+ raycastResults[0].gameObject.name);
                if (raycastResults[0].gameObject.name == "RawImage")//判断是否 是 自己要点击的UI
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {

                return false;
            }
           
        }
        /// <summary>
        /// 获取鼠标停留处UI
        /// </summary>
        /// <param name="canvas"></param>
        /// <returns></returns>
        public string GetOverUI(GameObject canvas)
        {
            PointerEventData pointerEventData = new PointerEventData(EventSystem.current);
            pointerEventData.position = Input.mousePosition;
            GraphicRaycaster gr = canvas.GetComponent<GraphicRaycaster>();
            List<RaycastResult> results = new List<RaycastResult>();
            gr.Raycast(pointerEventData, results);
            if (results.Count != 0)
            {
                Debug.Log("");
                return results[0].gameObject.name;
            }
            return null;
        }



    }
}



 6.鼠标点击 模型 触发事件

using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

namespace App.UI.Event
{
    public class RaycastFromMouse : MonoBehaviour, IPointerClickHandler, IPointerDownHandler, IPointerUpHandler, IDragHandler, IBeginDragHandler, IEndDragHandler
    {
        public Camera renderCamera;
        public RawImage rawImage;

        public void OnPointerClick(PointerEventData eventData)
        {
            // 获取鼠标点击位置
            Vector2 clickPosition = eventData.position;

            // 将屏幕坐标转换为 RawImage 的本地坐标
            Vector2 localPoint;
            RectTransformUtility.ScreenPointToLocalPointInRectangle(rawImage.rectTransform, clickPosition, eventData.pressEventCamera, out localPoint);

            // 将 RawImage 的本地坐标映射到 RenderTexture 的分辨率范围内
            Rect rect = rawImage.rectTransform.rect;
            Vector2 normalizedPoint = new Vector2((localPoint.x - rect.x) / rect.width, (localPoint.y - rect.y) / rect.height);

            // 将转换后的坐标转换为射线
            Ray ray = renderCamera.ViewportPointToRay(normalizedPoint);

            // 发射射线,检测是否与3D模型交互
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit))
            {
                // 获取物体上的 EventTrigger 组件
                EventTrigger eventTrigger = hit.collider.gameObject.GetComponent<EventTrigger>();

                // 如果组件存在,触发 Pointer Click 事件
                if (eventTrigger != null)
                {
                    ExecuteEvents.Execute(eventTrigger.gameObject, eventData, ExecuteEvents.pointerClickHandler);
                }
            }
        }
        
        private GameObject selectedObject;
        public void OnPointerDown(PointerEventData eventData)
        {
            RaycastHit hit;
            if (RaycastToRenderTexture(eventData, out hit))
            {
                EventTrigger eventTrigger = hit.collider.gameObject.GetComponent<EventTrigger>();
                if (eventTrigger != null)
                {
                    ExecuteEvents.Execute(eventTrigger.gameObject, eventData, ExecuteEvents.pointerDownHandler);
                    selectedObject = eventTrigger.gameObject;
                }
            }
        }

        public void OnPointerUp(PointerEventData eventData)
        {
            if (selectedObject != null)
            {
                EventTrigger eventTrigger = selectedObject.GetComponent<EventTrigger>();
                if (eventTrigger != null)
                {
                    ExecuteEvents.Execute(eventTrigger.gameObject, eventData, ExecuteEvents.pointerUpHandler);
                    selectedObject = null;
                }
            }
        }

        public void OnBeginDrag(PointerEventData eventData)
        {
            if (selectedObject != null)
            {
                EventTrigger eventTrigger = selectedObject.GetComponent<EventTrigger>();
                if (eventTrigger != null)
                {
                    ExecuteEvents.Execute(eventTrigger.gameObject, eventData, ExecuteEvents.beginDragHandler);
                }
            }
            
            GlobalEvent.Dispatch(UIExecuteEvent.OnBeginDragEvent, eventData);
        }
        
        public void OnDrag(PointerEventData eventData)
        {
            if (selectedObject != null)
            {
                EventTrigger eventTrigger = selectedObject.GetComponent<EventTrigger>();
                if (eventTrigger != null)
                {
                    ExecuteEvents.Execute(eventTrigger.gameObject, eventData, ExecuteEvents.dragHandler);
                }
            }
            
            GlobalEvent.Dispatch(UIExecuteEvent.OnDragEvent, eventData);
        }
        
        public void OnEndDrag(PointerEventData eventData)
        {
            if (selectedObject != null)
            {
                EventTrigger eventTrigger = selectedObject.GetComponent<EventTrigger>();
                if (eventTrigger != null)
                {
                    ExecuteEvents.Execute(eventTrigger.gameObject, eventData, ExecuteEvents.endDragHandler);
                }
            }
            
            GlobalEvent.Dispatch(UIExecuteEvent.OnEndDragEvent, eventData);
        }

        private bool RaycastToRenderTexture(PointerEventData eventData, out RaycastHit hit)
        {
            Vector2 clickPosition = eventData.position;
            Vector2 localPoint;
            RectTransformUtility.ScreenPointToLocalPointInRectangle(rawImage.rectTransform, clickPosition, eventData.pressEventCamera, out localPoint);
            Rect rect = rawImage.rectTransform.rect;
            Vector2 normalizedPoint = new Vector2((localPoint.x - rect.x) / rect.width, (localPoint.y - rect.y) / rect.height);
            Ray ray = renderCamera.ViewportPointToRay(normalizedPoint);

            return Physics.Raycast(ray, out hit);
        }
    }
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/926158.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

qt 实现音视频的分贝检测系统

项目场景&#xff1a; 目前的产品经常播放m3u8流&#xff0c;有的视频声音正常&#xff0c;有的视频声音就偏低&#xff0c;即使放到最大音量声音也是比较小&#xff0c;所以就产生了某种需求&#xff0c;能否自动感知视频声音的大小&#xff0c;如果发现声音比较小的情况&…

vue3项目初始

yarn add types/node -D是这个 下面 少到了S 这一步 就是 配置配置 src

高通 A12 设置-存储 存储总大小显示不正确问题

总存储大小计算原理&#xff1a; 系统获取存储大小是通过获取”/system”和”/data” 两个Directory 的和来计算的&#xff0c;即Environment.getDataDirectory().getTotalSpace() Environment.getRootDirectory().getTotalSpace() 问题一 &#xff1a;实际存储大小大于等于1…

网安周报|国防承包商Belcan泄露了带有漏洞列表的管理员密码

1.国防承包商Belcan泄露了带有漏洞列表的管理员密码 网络新闻研究团队发现了一个开放的 Kibana 实例&#xff0c;其中包含有关 Belcan、其员工和内部基础设施的敏感信息。Belcan 是一家政府、国防和航空航天承包商&#xff0c;提供全球设计、软件、制造、供应链、信息技术和数字…

企业在选择低代码平台时,应该注意哪些方面?

在 IT行业&#xff0c;“低代码”这个词可以说是近几年的热词了。低代码开发平台&#xff08;Low-Code Platform&#xff09;是一种新型的软件开发工具&#xff0c;它可以通过少量代码快速开发应用程序。通过采用低代码技术&#xff0c;开发者可以减少自己编写和测试应用程序的…

国际数字影像文创产业园开展企业法律的讲座

2023年8月18日14:30-16:10由成都市金牛区人民政府五块石街道办事处指导&#xff0c;国际数字影像文创产业园区、成都树观法律咨询服务有限公司主办&#xff0c;成都目莓商业运营管理有限公司协办的“法律讲座沙龙”活动在数媒大厦5楼共享会议室成功开展。 本次活动主题为“企业…

网络工程----小型网络配置1

此次作业设计&#xff1a; 硬件&#xff1a;二层交换机、三层交换机、路由、服务器、pc 配置知识&#xff1a;dhcp, dns配置&#xff0c;vlan划分&#xff0c;不同vlan间通信&#xff0c;静态路由&#xff0c;Nat动态地址&#xff0c; nat server映射&#xff0c;acl 配置命…

海外ios应用商店优化排名因素之评级与评论

评分显示在搜索结果中&#xff0c;直接影响转化率&#xff0c;而评论可以在应用页面上看到&#xff0c;评级和评论是我们无法直接控制的因素。但是我们仍然可以通过了解用户的需求并兑现承诺来尝试改进它。 1、关于用户的评论。 抱怨的用户在讲述某个问题时总是会给出最好的反…

Keil编译告警 warning: #1-D: last line of file ends without a newline

如题所示&#xff0c;Keil编译的时候&#xff0c;如果遇到了这个问题&#xff0c;就是文件最后一行并不是一个新行结尾。这个问题不影响编译结果&#xff0c;但是强迫症就受不了。 原因是源文件最后一行可能空出来了&#xff0c;但是有空格&#xff0c;如下所示&#xff1a; 这…

ACL2023 Prompt 相关文章速通 Part 1

Accepted Papers link: ACL2023 main conference accepted papers 文章目录 Accepted PapersPrompter: Zero-shot Adaptive Prefixes for Dialogue State Tracking Domain AdaptationQuery Refinement Prompts for Closed-Book Long-Form QAPrompting Language Models for Lin…

亚马逊评论后多久显示?有没有快速留评的方法?

通常情况下&#xff0c;亚马逊上的产品评论会在提交后的一到两天内显示出来。然而&#xff0c;实际的显示时间可能会因多种因素而有所不同&#xff0c;包括评论审核时间、产品销量、亚马逊服务器负载等等。在某些情况下&#xff0c;评论可能会更快地显示出来&#xff0c;而在其…

Ubuntu 22.04.3 LTS 维护更新发布

导读近日消息&#xff0c;Canonical 今天发布了代号为 Jammy Jellyfish、长期支持的 Ubuntu 22.04 第 3 个维护版本更新&#xff0c;距离上个版本相隔 6 周时间。 Ubuntu 22.04.3 LTS 最大的亮点在于内核升级到 Linux Kernel 6.2&#xff0c;此外 Mesa 图形堆栈也升级到 23.0.…

徐庆臣(黑客洗白者)个人介绍

徐庆臣&#xff08;黑客洗白者&#xff09;&#xff0c;具备10年以上研发、渗透测试和网络信息安全领域从业经验&#xff0c;具有较强的网络安全管理、技术实战项目经验。曾就职于新浪、用友等互联网知名企业&#xff0c;并担任项目经理和安全技术总监等负责人角色&#xff0c;…

Modelica由入门到精通—为什么要学习Modelica语言

1.为什么要学习Modelica语言 本人正在研究Modelica 多领域统一建模仿真语言&#xff0c;特此做学习入门介绍&#xff0c;希望可以帮助需要的小伙伴。 文章目录 1.为什么要学习Modelica语言一、背景二、系统建模与仿真2.1 系统仿真与系统模型2.2 仿真价值与可靠性 三、物理建模…

kettle开发-Day42-远程执行作业

目录 前言&#xff1a; 一、远程执行 1、先看定义 2、前置条件 2.1网络畅通 2.2数据库DB连接一致 二、实战案例-Windows 1、初始配置-被远程端 1.1启动carte服务 1.2cmd 命令启动carte服务 2、初始化-远程端 3、实际应用 3.1、错误案例 3.2、正确案例 三、总结 前言&…

react import 引用失效 node_modules/@types/react/index.d.ts not a module.ts

问题描述 react ts的项目&#xff0c;正常使用vs code打开&#xff0c; 先运行 npm install 安装依赖过后 结果所有的react引用依旧标红&#xff0c;如下图所示&#xff1a; 点击红线 show problem(查看问题)&#xff0c;提示node_modules/types/react/index.d.ts not a mod…

day-31 代码随想录算法训练营(19)贪心part01

455.分发饼干 思路一&#xff1a;贪心思路&#xff0c;大饼干先分给大胃口 思路二&#xff1a;小饼干先分给小胃口 376.摆动序列 分析摆动&#xff1a;记 presub 为前面与当前数之差&#xff0c;lastsub 为当前与后面数之差 思路&#xff1a; 1.正常摆动时&#xff0c;需要 …

Talk | 上海交通大学官同坤:识别任意文本,隐式注意力与字符间蒸馏在文本识别中的应用

本期为TechBeat人工智能社区第525期线上Talk&#xff01; 北京时间8月23日(周三)20:00&#xff0c;上海交通大学博士生—官同坤的Talk已准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “隐式注意力与字符间蒸馏在文本识别中的应用”&#xff0c;分享了识别…

基于Jenkins+Git+Ansible 发布PHP 项目-------从小白到大神之路之学习运维第88天

第四阶段提升 时 间&#xff1a;2023年8月25日 参加人&#xff1a;全班人员 内 容&#xff1a; 基于JenkinsGitAnsible 发布PHP 项目 目录 基于JenkinsGitAnsible 发布PHP 项目 一、部署PHP 运行环境 二、主机环境配置 三、Tomcat主机操作&#xff1a; 四、Jenkins主…

【PHP】echo 输出数组报Array to string conversion解决办法

代码&#xff1a; <?PHP echo "Hello World!";$demoName array("kexuexiong","xiong");echo "<pre>";var_dump($demoName);echo $demoName; print_r($demoName);echo "</pre>"; ?>输出结果&#xff1…