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);
        }
    }
}
相关推荐
叶帆2 天前
【YFIOs】用C#开发硬件之设备上云
开发语言·unity·c#
久数君2 天前
AI三维建模工具“造形家”:地理场景三维化的高效解决方案
unity·glb·ai算法·ai三维建模工具·地图框选·造形家·城市建筑模型
会思考的猴子2 天前
Unity VFX 属性 Postion 和 TargetPostion
unity
hai3152475433 天前
九章编程法 · 猜数字游戏 (GW-BASIC 重构版) *
人工智能·microsoft·游戏引擎·游戏程序
心前阳光3 天前
Unity资源导入之自动化资源导入
unity·自动化·游戏引擎
心前阳光3 天前
Unity之2021.3.45f2c1发布安卓程序遇到的问题
android·unity·游戏引擎
纪纯3 天前
PicoVR Unity Integration SDK 3.4 常用交互API
unity·游戏引擎·vr·pico
龙智DevSecOps解决方案3 天前
3A 游戏优化技术栈:如何打通引擎级分析工具与 DevOps 持续集成管线?
unity·性能优化·游戏开发·技术美术·perforce·unrealengine
葛兰岱尔3 天前
从 SolidWorks 到 Three.js,从 Inventor 到 Unity——制造业CAD模型“几何-语义一体化“转换,不再是天方夜谭!
开发语言·javascript·unity
鼎艺创新科技3 天前
三维电子沙盘中OSGB倾斜摄影数据的加载与渲染
游戏引擎·cocos2d