IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> [UGUI进阶知识十六]一些自定义UI API 和 UGUI里面的总结 -> 正文阅读

[游戏开发][UGUI进阶知识十六]一些自定义UI API 和 UGUI里面的总结

做功能时候,有时需要的不仅仅是unity的基础API,更是需要在此基础上进行加工成一些工具方法,这里放一些以前用到的功能的工具方法

自定义API

将两个UI的Recttransform属性相同

 public void SetRecttransformAttrSame(RectTransform toSetRecttransform, RectTransform copyFromRectTransform)
    {
        toSetRecttransform.anchorMax = copyFromRectTransform.anchorMax;
        toSetRecttransform.anchorMin = copyFromRectTransform.anchorMin;
        toSetRecttransform.pivot = copyFromRectTransform.pivot;
        toSetRecttransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, copyFromRectTransform.rect.width);
        toSetRecttransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, copyFromRectTransform.rect.height);
        toSetRecttransform.position = copyFromRectTransform.position; 
    }

得到当前屏幕分辨率与Canvas Scaler参考分辨率下的高度比或者宽度比,要求传入的RectTransform是全屏大小的

  /// <summary>
    /// 获得实际屏幕宽度和标准屏幕宽度比值
    /// </summary>
    /// <param name="canvasRect"></param>
    /// <returns></returns>
    public static float GetResolutionWidthRatio(RectTransform canvasRect)
    {
        float currentResolutionWidth;

#if UNITY_EDITOR
        int canvasDisplay =  canvasRect.GetComponent<Canvas>().targetDisplay;
        currentResolutionWidth = Display.displays[canvasDisplay].renderingWidth;
#else
        currentResolutionWidth = Screen.currentResolution.width;
#endif
        //这里standardResolutionHeight是CanvasScaler下的Reference Resolution的width即 canvasScaler.referenceResolution.x
        float ratio = (currentResolutionWidth * 1f) / Const.standardResolutionWidth;
        return ratio;
    }
    
    /// <summary>
    /// 获得实际屏幕高度和标准屏幕高度比值
    /// </summary>
    /// <param name="canvasRect"></param>
    /// <returns></returns>
    public static float GetResolutionHeightRatio(RectTransform canvasRect)
    {
        float currentResolutionHeight;

#if UNITY_EDITOR
        int canvasDisplay =  canvasRect.GetComponent<Canvas>().targetDisplay;
        currentResolutionHeight = Display.displays[canvasDisplay].renderingHeight;
#else
        currentResolutionHeight = Screen.currentResolution.height;
#endif
        //这里standardResolutionHeight是CanvasScaler下的Reference Resolution的height 即 canvasScaler.referenceResolution.y
        float ratio = (currentResolutionHeight * 1f) / Const.standardResolutionHeight;
        return ratio;
    }

获得鼠标位置在UI中的局部坐标

public static Vector2 GetMouseLocalPos(Vector3 screenPos, Transform transform,
            RenderMode _canvasMode, Camera _camera, float canvasDistance)
        {
            Vector3 worldPoint = screenPos;
            switch (_canvasMode)
            {
                case RenderMode.ScreenSpaceCamera:
                    worldPoint = _camera.ScreenToWorldPoint(  new Vector3(screenPos.x, screenPos.y, canvasDistance));
                    // Debug.Log(" GetMouseLocalPos worldPoint " + worldPoint + " eventData.position " + eventData.position);
                    
                    break;
                case RenderMode.ScreenSpaceOverlay:
                    worldPoint = screenPos;
                    break;
            }
            
            Vector3 localPos = transform.InverseTransformPoint(worldPoint);
            // Debug.Log(" localPos " + localPos);
            
            return localPos;
        }

根据局部坐标获得对应的uv

 /// <summary>
        /// 获取pivot点和uv原点的距离
        /// pivot坐标系的xy范围都是[0-1]
        /// 当pivot在图片左下角时,pivot的xy都是0,右上角都为1
        /// uv的u和v范围也都是[0-1]
        /// </summary>
        /// <returns></returns>
        public static Vector2 GetLocalPosUVCoordinate(Vector2 localPos, RectTransform rectTransform)
        {
            Vector2 remedyOffset = 
                new Vector2(
                    rectTransform.pivot.x * rectTransform.rect.width,
                    rectTransform.pivot.y * rectTransform.rect.height
                );

            Vector2 unormalizedLocalPosUVCoordinate = localPos + remedyOffset;

            Vector2 localPosUVCoordinate =
                new Vector2(
                    unormalizedLocalPosUVCoordinate.x / rectTransform.rect.width ,
                    unormalizedLocalPosUVCoordinate.y / rectTransform.rect.height 
                );
            
            return localPosUVCoordinate;
        }

将局部坐标转换为以屏幕中心为原点,向右为x轴正方向,向上为y轴正方向的相对坐标

 public static Vector2 TransformLocalToScreenCenterPos(Vector2 localPos, 
            RectTransform rectTransform, Canvas canvas, Camera uiCamera, RenderMode canvasRenderMode)
        {
            switch (canvasRenderMode)
            {
                case RenderMode.ScreenSpaceOverlay:
                    return OverlayTransformLocalToCanvasCenterPos(localPos, rectTransform, canvas);
                    break;
                case RenderMode.ScreenSpaceCamera:
                    return CameraTransformLocalToCanvasCenterPos(localPos, rectTransform, canvas, uiCamera);
                    break;
                case RenderMode.WorldSpace:
                    return Vector2.zero;
                    break;
            }
            return Vector2.zero;

        }


 /// <summary>
        /// 在设置是ScreenSpace-Overlay并且pivot是(0.5,0.5)的根Canvas时
        /// shader中的局部坐标系原点是根Canvas的中心
        /// 这里将某UI的局部坐标系转换到以Canvas中心为原点的相对坐标
        /// 这里假设根Canvas的pivot是(0.5, 0.5)
        /// </summary>
        /// <returns></returns>
 public static Vector2 OverlayTransformLocalToCanvasCenterPos(Vector2 localPos, 
            RectTransform rectTransform, Canvas canvas)
        {
            Vector2 screenCenterScreenPos = GetOverlayCanvasCenterScreenPos(canvas);
            
            //在设置是ScreenSpace-Overlay的Canvas中,
            //TransformPoint转换出来的是屏幕坐标
            //屏幕坐标的原点在屏幕左下角
            Vector2 posScreen = rectTransform.TransformPoint(localPos);
            
            //获得屏幕坐标系下,相对于从屏幕中心到localPos的向量
            //即localPos到以Canvas中心为原点的相对坐标
            Vector2 oppositePos = posScreen - screenCenterScreenPos;
            
            return oppositePos;
        }


       /// <summary>
        /// 在设置是ScreenSpace-Camera并且pivot是(0.5,0.5)的根Canvas时
        /// shader中的局部坐标系原点是根Canvas的中心
        /// 这里将某UI的局部坐标系转换到以Canvas中心为原点的相对坐标
        /// 这里假设根Canvas的pivot是(0.5, 0.5)
        /// </summary>
        /// <returns></returns>
        public  static  Vector2 CameraTransformLocalToCanvasCenterPos(Vector2 localPos, 
            RectTransform rectTransform, Canvas canvas, Camera uiCamera)
        {
            Vector2 screenCenterScreenPos = GetCameraCanvasCenterScreenPos(canvas);

            //在设置是ScreenSpace-Camera的Canvas中,
            //TransformPoint转换出来的是屏幕坐标
            //屏幕坐标的原点在屏幕左下角
            Vector3 posWorld = rectTransform.TransformPoint(localPos);

            Vector3 posScreen =  uiCamera.WorldToScreenPoint(posWorld);
            
            //获得屏幕坐标系下,相对于从屏幕中心到localPos的向量
            //即以Canvas中心为原点到localPos的相对坐标
            Vector2 oppositePos = new Vector2(posScreen.x, posScreen.y)  - screenCenterScreenPos;
            
            return oppositePos;
        }
        

获取在ScreenSpace-Camera模式下的全屏大小的Canvas的屏幕中心坐标

 public static Vector2 GetCameraCanvasCenterScreenPos(Canvas canvas)
        {
            //屏幕中心的屏幕坐标 
            //在编辑器中,Screen.currentResolution是整个显示屏的宽高
            //所以不能用这种办法
            // Vector2 screenCenterScreenPos = new Vector2(
            //     Screen.currentResolution.width  / 2f,
            //     Screen.currentResolution.height / 2f
            // );
            RectTransform canvasRectTrn = canvas.GetComponent<RectTransform>();
            
            //canvasRectTrn.rect获取的与Screen.currentResolution单位相同
            //都是屏幕坐标的单位
            Vector2 screenCenterScreenPos = new Vector2(
                canvasRectTrn.rect.width  / 2f,
                canvasRectTrn.rect.height / 2f
            );
            
            // Debug.Log(" GetCameraCanvasCenterScreenPos " + screenCenterScreenPos);
            
            return screenCenterScreenPos;
        }

获取在ScreenSpace-Overlay模式下的全屏大小的Canvas的屏幕中心坐标

public static Vector2 GetOverlayCanvasCenterScreenPos(Canvas canvas)
        {
            //屏幕中心的屏幕坐标 
            //在编辑器中,Screen.currentResolution是整个显示屏的宽高
            //所以不能用这种办法
            // Vector2 screenCenterScreenPos = new Vector2(
            //     Screen.currentResolution.width  / 2f,
            //     Screen.currentResolution.height / 2f
            // );
            RectTransform canvasRectTrn = canvas.GetComponent<RectTransform>();
            
            //canvasRectTrn.rect获取的与Screen.currentResolution单位相同
            //都是屏幕坐标的单位
            Vector2 screenCenterScreenPos = new Vector2(
                      canvasRectTrn.rect.width  / 2f,
                      canvasRectTrn.rect.height / 2f
                );
            
            return screenCenterScreenPos;
        }

总结

二屏UI对一屏UI的映射

有个需求是将二屏的UI映射到一屏,这种映射需求虽然很少遇到,但还是记录一下。

RawImage映射

RawImage映射做法只能是这个Ui的Canvas是ScreenSpace-Camera,并且对应的Camera指定某个相机,相机再将结果映射到某个RenderTexture上面。这个RenderTexture覆盖二屏 Overlay的UI不能映射,因为相机看不到Overlay的UI,即使角度和位置调节得很对。

相机渲染Display2

前面的做法一样,但是相机直接是设置渲染目标是Display2.注意不能有其他的Display2的Overlay的UI或者其他Display2的深度更大的相机,不然渲染结果会被覆盖

直接复制

如果不考虑实时,这种方法是很省性能的。
将一屏的某部分UI用GameObject.Instantiate直接复制到二屏,复制的物体下面的所有子物体会一起复制过去。
注意被复制的物体的所有父物体的REctTransform的属性和复制出来的所有父物体的属性都一致,效果才有保证。

实时运行读取配置表生成位置时注意

举个例子,当Overlay的UI地图的碰撞点是在38402160的Canvas Scaler的ReferenceResolution分辨率下摆放的,这时摆放位点的宽高位置上限是3840和2160。当屏幕调节成其他屏幕分辨率的时候,例如变成了19201080,为了让摆放能够正确,需要根据实际的分辨率与参考分辨率得到比例,在这个的基础上进行重新计算位置。

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-03-11 22:32:23  更:2022-03-11 22:33:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 14:48:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码