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);
        }
    }
}
相关推荐
超龄魔法少女7 小时前
[Unity] ShaderGraph动态修改Keyword Enum,实现不同效果一键切换
unity·技术美术·shadergraph
蔗理苦8 小时前
2024-12-24 NO1. XR Interaction ToolKit 环境配置
unity·quest3·xr toolkit
花生糖@8 小时前
Android XR 应用程序开发 | 从 Unity 6 开发准备到应用程序构建的步骤
android·unity·xr·android xr
向宇it9 小时前
【从零开始入门unity游戏开发之——unity篇02】unity6基础入门——软件下载安装、Unity Hub配置、安装unity编辑器、许可证管理
开发语言·unity·c#·编辑器·游戏引擎
虾球xz9 小时前
游戏引擎学习第55天
学习·游戏引擎
虾球xz11 小时前
游戏引擎学习第58天
学习·游戏引擎
ue星空13 小时前
虚幻引擎结构之UWorld
游戏引擎·虚幻
ue星空13 小时前
虚幻引擎结构之ULevel
游戏引擎·虚幻
向宇it13 小时前
【从零开始入门unity游戏开发之——unity篇01】unity6基础入门开篇——游戏引擎是什么、主流的游戏引擎、为什么选择Unity
开发语言·unity·c#·游戏引擎
神洛华16 小时前
Y3地图制作1:水果缤纷乐、密室逃脱
编辑器·游戏引擎·游戏程序