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

项目工程:unity模型显示在UI上并交互(点击、旋转、缩放)资源-CSDN文库

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.mfbz.cn/a/90449.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【微服务】05-网关与BFF(Backend For Frontend)

文章目录 1.打造网关1.1 简介1.2 连接模式1.3 打造网关 2.身份认证与授权2.1 身份认证方案2.1.1 JWT是什么2.1.2 启用JwtBearer身份认证2.1.3 配置身份认证2.1.4 JWT注意事项 1.打造网关 1.1 简介 BFF(Backend For Frontend)负责认证授权&#xff0c;服务聚合&#xff0c;目标…

CMake3.27+OpenCV4.8+VS2019+CUDA配置

1、准备工作 CMake3.27+OpenCV4.8+opencv_contrib-4.8.0+CUDA+CUDNN+TensorRT下载好并安装cuda 2、正式开始安装 启动CMake开始配置 打开刚解压的cmake文件夹中找到bin目录下的cmake-gui.exe 点击cmake中左下角的 Configure进行第一次配置,会弹出选择环境对话框 …

Jmeter压测测试

Jmeter安装启动 1、Jmeter下载安装 模拟真正的大量并发请求 下载Jmeter&#xff1a;Apache JMeter - Download Apache JMeter 解压apache-jmeter-5.4.1.zip文件至目录下&#xff08;不要有空格和中文&#xff09; 2、配置JMETER_HOME 在系统中搜索设置 打开设置&#xff0…

【LeetCode-中等题】189. 轮转数组

题目 题解一&#xff1a;开辟数组 取模运算寻找位置(ik)mod n 新位置 思路&#xff1a;通过&#xff0c;开辟数组 取模运算寻找新位置------位置(ik)mod n 新位置 int[] newNums new int[nums.length];for(int i 0;i<nums.length;i){newNums[(ik)%nums.length] nums[i…

MBR400100CT-ASEMI肖特基模块400A 100V

编辑&#xff1a;ll MBR400100CT-ASEMI肖特基模块400A 100V 型号&#xff1a;MBR400100CT 品牌&#xff1a;ASEMI 封装&#xff1a;M2 恢复时间&#xff1a;&#xff1e;50ns 正向电流&#xff1a;400A 反向耐压&#xff1a;100V 芯片个数&#xff1a;2 引脚数量&…

算法通关村第十关——快速排序算法

1 快速排序基本过程 快速排序的是将分治法运用到排序问题的典型例子。力扣912题&#xff0c;给你一个整数数组 nums&#xff0c;请你将该数组升序排列。 基本思想&#xff1a;是通过随机标记一个pivot元素将含有n个元素的序列划分为左右两个子序列left和right&#xff0c;其中…

el-table动态合并单元格

el-table使用这个方法合并单元格&#xff0c;:span-method“hbcell” <el-table size"small" :data"table.data" border empty-text"暂无数据" :cell-style"cellStyle" :header-cell-style"tableHeaderColor":span-meth…

Linux 终端命令之文件目录操作,对比Dos相关命令

目录 前言 基础命令&#xff08;文件目录相关的&#xff09; cd命令 【英文帮助】 【对应Dos命令】 pwd命令 【英文帮助】 【对应Dos命令】 ls命令 【英文帮助】 【对应Dos命令】 tree命令 【英文帮助】 【对应Dos命令】 mkdir命令 【英文帮助】 【对应Dos命令…

vscode的远程代码调试

目录 ssh连接 xdebug调试 ssh连接 在vscode中下载该插件 这里用虚拟机测试&#xff0c;这里用虚拟机测试&#xff0c;注意ssh是可以连接的 然后安装好remote后&#xff0c;点击左下角的>< 在弹出的这个上选择connect to host连接一台主机 配置完用户名和IP后再点一次发…

xsschallenge通关(11-15)

level 11 老规矩&#xff0c;先查看源码&#xff0c;做代码审计&#xff1a; <?php ini_set("display_errors", 0); $str $_GET["keyword"]; $str00 $_GET["t_sort"]; $str11$_SERVER[HTTP_REFERER]; $str22str_replace(">&quo…

微软宣布在 Excel 中使用 Python:结合了 Python 的强大功能和 Excel 的灵活性。

文章目录 Excel 中的 Python 有何独特之处&#xff1f;1. Excel 中的 Python 是为分析师构建的。高级可视化机器学习、预测分析和预测数据清理 2. Excel 中的 Python 通过 Anaconda 展示了最好的 Python 分析功能。3. Excel 中的 Python 在 Microsoft 云上安全运行&#xff0c;…

史上最全 App功能测试点分析

1.2测试周期 测试周期可按项目的开发周期来确定测试时间&#xff0c;一般测试时间为两三周&#xff08;即 15个工作日&#xff09;&#xff0c; 根据项目情况以及版本质量可适当缩短或延长测试时间。正式测试前先向主管确认项目排期。 1.3测试资源 测试任务开始前&#xff…

手把手教你搭建一个盲盒小程序,轻松掌握开发技巧

在当今社交媒体时代&#xff0c;微信公众号已成为企业、个人传播和推广的重要工具。而微信公众号盲盒小程序则是一个更为创新和互动的方式&#xff0c;能够吸引更多用户的关注和参与。下面&#xff0c;我们将为大家介绍一下微信公众号盲盒小程序的制作完全攻略。 1. 注册登录【…

MySQL数据库基本操作

目录 一、数据库中常用的数据类型 二、常用命令与操作 1.DDL数据库定义语言 1、登录用户的数据库 2、查看当前服务器中的数据库 3、切换/进入数据库 并 查看数据库中包含的表 4、查看数据库中表的结构 5、创建数据库 7、展示创建数据表时的结构 8、创建表&#xff0c…

根据案例写PLC程序-红绿灯控制

案例&#xff1a; 1、南北方向红灯点亮30s后熄灭&#xff1b; 2、在点亮南北方向红灯的同时点亮东西方向绿灯&#xff0c;并在点亮25s后&#xff0c;以0.5s熄灭0.5s点亮的时间闪烁3次后熄灭&#xff1b; 3、在东西方向绿灯熄灭后&#xff0c;东西方向黄灯点亮2s后熄灭&#xff…

Redis知识点总结

概述 Redis诞生于2009年&#xff0c;全称是Remote Dictionarty Server(远程词典服务器) 只支持单线程 非关联&#xff1a;主要指的是表中没有主外键等概念 Redis是一款内存数据库&#xff0c;主要存储键值对类型的数据 基本用法 注意&#xff1a;该操作是在cli中进行的 首…

pytestx重新定义接口框架设计

概览 脚手架&#xff1a; 目录&#xff1a; 用例代码&#xff1a; """ 测试登录到下单流程&#xff0c;需要先启动后端服务 """test_data {"查询SKU": {"skuName": "电子书"},"添加购物车": {"sk…

Matlab之智能优化算法函数调用

1.句柄函数 句柄函数即我们要求的目标函数&#xff0c;以下三种算法的调用仅是求解最小值&#xff0c;若要求目标函数的最大值&#xff0c;可在返回结果中加负号。 function value Get_Fitness(x,y)value x^2 y^2;% 若要求x^2 y^2最大值可设value -(x^2 y^2); end句柄函数…

跨境新手看过来!各国营销禁忌盘点!别再盲目踩雷了!

本土化是跨境卖家出海制胜的关键因素之一&#xff0c;不管是卖家的产品&#xff0c;还是营销推广策略&#xff0c;都要符合目标市场的习惯&#xff0c;才会有较好的效果。而与此相反的&#xff0c;如果卖家在营销过程中&#xff0c;踩到了营销雷区&#xff0c;那结果也可想而知…

机器视觉应用开发四大软件,那一个对我们从0到1建设你的机器视觉知识体系更好

我们首先要理解什么是知识体系&#xff1a; 我们身处一个知识爆炸时代&#xff0c;我们面对各种课程&#xff0c;各种知识&#xff0c;“自身学习”&#xff0c;“高效记忆”&#xff0c;“批判性思维”&#xff0c;“解决问题的能力”。各种平台课程太多&#xff0c;各种买买…