Unity實現在UI面板中單獨查看設備模型且自由控制三維模型旋轉查看

一、實現思路

①創建一個RenderTexture,渲染設備模型;

②創建一個攝像機,就只照射UI面板的設備,且移除AudioListener組件;

③設置該創建出來的只照射UI面板設備攝像機的【Target Texture】屬性爲該RenderTexture;

④創建一個顯示設備模型的圖片組件RawImage,且指定該RawImage的屬性Texture爲RenderTexture;

⑤最後創建一個設備物體在這個只照射UI面板設備的攝像機前面即可。

二、實現效果

 

三、控制三維物體自由旋轉

①控制設備自由旋轉的核心腳本如下:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace MyFunction
{

    public class ModelRotationController : MonoBehaviour
    {
        //變量枚舉
        public enum RotationAxes
        {
            MouseXAndY = 0,
            MouseX = 1,
            MouseY = 2
        }

        public bool interactable;

        [Header("操作的物體")]
        public GameObject Obj;
        [Header("主相機")]
        public GameObject MainCamera;

        [Space(20)]
        [Header("旋轉速度"), Range(0, 2)]
        public float aroundRadius = 0.5f;//角速度
        [Header("自動旋轉時間間隔"), Range(0, 10)]
        public float timeinterval = 4f;//時間間隔
        [Header("上下翻轉開關")]
        public bool SwitchVertical = false;
        [Header("上下旋轉角度限制")]
        public float eulerUp = 60;
        public float eulerDown = -60f;
      
        [Space(20)]

        [Header("默認距離")]
        public float distence = 6f;
        [Header("縮放速度"), Range(0, 30)]
        public float speed = 15;       //縮放速度
        [Header("縮放最遠距離"), Range(0, 50)]
        public float distenceMax = 20f;
        [Header("縮放最近距離"), Range(2, 20)]
        public float distenceMin = 3f;
        [Header("縮放最大速度")]
        public float maxSpeed = 30;
        [Header("縮放最小速度")]
        public float minSpeed = 1;
        [Header("縮放加速度")]
        public float Acceleration = 1;


        float m_rotationY = 0f;                                          //偏移量
        [HideInInspector]
        private Vector3 direction = new Vector3(0, 1, 0);//自動旋轉的方向
        [HideInInspector]
        public bool Switch_detail = false;//細節開關
        [HideInInspector]
        public RotationAxes m_axes = RotationAxes.MouseXAndY;                   //實例化枚舉

        public static ModelRotationController _instance;

        [HideInInspector]
        public Vector3 eulerObj;

        float eulerYNow;

        float angled;//當前角度



        float _TimeNow = 0f;
        float _EulerX = 0;
        float _EulerY = 0;
        bool auto = false;
        public float notChangeminDistance;
        public float notChangemaxDistance;
        bool setminValue = true;
        bool setmaxValue = true;

        [HideInInspector]
        public float EulerOffentY; //Y值偏移量

        private void Awake()
        {
            notChangeminDistance = distenceMin;
            notChangemaxDistance = distenceMax;
            EulerOffentY = 0;
            _instance = this;
            interactable = true;
            maxSpeed = speed * 2;
        }

        private void Update()
        {
            if (Obj)
            {
                eulerObj = Obj.transform.rotation.eulerAngles;
            }

            if (Obj != null && interactable && !GameObject.Find("Dropdown List") && !GameObject.Find("AlarmTable") && !Switch_detail)
            {
                ManualController();
                if (auto)
                {
                    _TimeNow = 0;
                    AutoController();
                }
                else
                {
                    _TimeNow += Time.deltaTime;
                }


                VerticalRotate();
                HoriZontalRotate();

                CameraMove();

            }

        }

        /// <summary>
        /// 交互控制開關
        /// </summary>
        public void CameraSwitch()
        {
            interactable = !interactable;
        }

        #region 相機控制

        /// <summary>
        /// 相機縮放
        /// </summary>
        void CameraMove()
        {
            if (Obj != null)
            {
                // MainCamera.transform.LookAt(Obj.transform);
            }

            if (Input.GetAxis("Mouse ScrollWheel") > 0)
            {
                auto = false;
                _TimeNow = 0;
                distence = Mathf.Sqrt((Obj.transform.position - MainCamera.transform.position).sqrMagnitude);
                //distence = Obj.transform.position.z - MainCamera.transform.position.z;\


                MainCamera.transform.Translate(new Vector3(0, 0, 1) * speed * Time.deltaTime, Space.Self);
                if (distence < distenceMin)
                {
                    MainCamera.transform.position = Obj.transform.position - new Vector3(0, 0, distenceMin);
                }
                else
                {
                    //近慢
                    if (Mathf.Approximately(speed, minSpeed))
                    {
                        if (setminValue)
                        {
                            notChangeminDistance = distence;
                            setminValue = false;
                        }

                    }
                    if (distence < notChangemaxDistance)
                    {
                        speed -= Acceleration;
                        speed = Mathf.Clamp(speed, minSpeed, maxSpeed);
                    }

                }
            }
            else if (Input.GetAxis("Mouse ScrollWheel") < 0)
            {
                auto = false;
                _TimeNow = 0;
                distence = Mathf.Sqrt((Obj.transform.position - MainCamera.transform.position).sqrMagnitude);


                MainCamera.transform.Translate(new Vector3(0, 0, -1) * speed * Time.deltaTime, Space.Self);

                if (distence > distenceMax)
                {
                    MainCamera.transform.position = Obj.transform.position - new Vector3(0, 0, distenceMax);
                }
                else
                {
                    //遠快
                    if (Mathf.Approximately(speed, maxSpeed))
                    {
                        if (setmaxValue)
                        {
                            notChangemaxDistance = distence;
                            setmaxValue = false;
                        }
                    }
                    if (distence > notChangeminDistance)
                    {
                        speed += Acceleration;

                        speed = Mathf.Clamp(speed, minSpeed, maxSpeed);
                    }

                }
            }
        }

        /// <summary>
        /// 相機對象重置
        /// </summary>
        /// <param name="cur"></param>
        public void MachineReset(GameObject cur)
        {
            notChangeminDistance = 0;
            notChangemaxDistance = 30;
            setminValue = true;
            setmaxValue = true;
            speed = 15;
            Obj = cur;
            distence = 6;
            if (Switch_detail)
            {
                MainCamera.transform.position = Obj.transform.position - new Vector3(0, 0, 4);
            }
            else
            {
                MainCamera.transform.position = new Vector3(Obj.transform.position.x, Obj.transform.position.y, -distence);
            }
        }
        #endregion

        #region 物體旋轉控制
        /// <summary>
        ///手動控制
        /// </summary>
        void ManualController()
        {
            if (Input.GetKey(KeyCode.Mouse0))
            {
                auto = false;
                _TimeNow = 0;
                Obj.transform.Rotate(new Vector3(0, _EulerY, 0), Space.Self);
                EulerOffentY += _EulerX;
                if (EulerOffentY > eulerUp)
                {
                    EulerOffentY = eulerUp;
                    _EulerX = 0;
                }
                else if (EulerOffentY < eulerDown)
                {
                    EulerOffentY = eulerDown;
                    _EulerX = 0;
                }
                Obj.transform.Rotate(new Vector3(_EulerX, 0, 0), Space.World);
            }
            else if (_TimeNow > timeinterval && Input.GetAxis("Mouse ScrollWheel") == 0f)
            {
                auto = false;  //關閉自動旋轉
            }
        }

        /// <summary>
        /// 自動旋轉
        /// </summary>
        void AutoController()
        {
            Obj.transform.Rotate(direction * aroundRadius);
        }

        /// <summary>
        /// 水平旋轉
        /// </summary>
        void HoriZontalRotate()
        {
            float eularAboutY = -Input.GetAxis("Mouse X") * aroundRadius * 200 * Time.deltaTime;
            //Debug.Log("eularAboutY:"+ eularAboutY);
            _EulerY = eularAboutY;
        }

        /// <summary>
        /// 垂直旋轉
        /// </summary>
        void VerticalRotate()
        {
            if (SwitchVertical)
            {
                float eularAboutX = Input.GetAxis("Mouse Y") * aroundRadius * 200 * Time.deltaTime;
                //Debug.Log("eularAboutX:" + eularAboutX);
                _EulerX = eularAboutX;

            }
        }

        /// <summary>
        /// 角度限制
        /// </summary>
        /// <param name="minZ">最小角度</param>
        /// <param name="maxZ">最大角度</param>
        public void RotateLimite()
        {
            if (Obj)
            {
                float _EulerOfY = Obj.transform.rotation.eulerAngles.y;
                Mathf.Clamp(CheckAngle(_EulerOfY), eulerDown, eulerUp);
                Obj.transform.rotation = Quaternion.Euler(_EulerOfY, Obj.transform.rotation.y, Obj.transform.rotation.z);
            }
        }

        /// <summary>
        /// 角度限制操作
        /// </summary>
        /// <param name="angle">當前角度</param>
        /// <param name="min">最小角度</param>
        /// <param name="max">最大角度</param>
        /// <returns></returns>
        protected float CheckAngle(float angle, float min, float max)
        {
            if (angle < 90 || angle > 270)
            {       // if angle in the critic region...
                if (angle > 180) angle -= 360;  // convert all angles to -180..+180
                if (max > 180) max -= 360;
                if (min > 180) min -= 360;
            }
            angle = Mathf.Clamp(angle, min, max);
            if (angle < 0) angle += 360;  // if angle negative, convert to 0..360
            return angle;
        }
        /// <summary>
        /// 角度轉換方法
        /// </summary>
        /// <param name="angle"></param>
        /// <returns></returns>
        protected float CheckAngle(float value)  // 將大於180度角進行以負數形式輸出
        {
            float angle = value - 180;

            if (angle > 0)
            {
                return angle - 180;
            }

            if (value == 0)
            {
                return 0;
            }

            return angle + 180;
        }
        #endregion
    }
}

②將該腳本掛載到任意物體上,然後指定對應需要旋轉的設備和照射三維模型的攝像機即可

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章