首页 > 其他分享 >【Unity UGUI】UGUI适配

【Unity UGUI】UGUI适配

时间:2023-11-15 18:12:31浏览次数:38  
标签:RT 适配 Screen Unity currentResolution mParentCanvesRT UGUI safeArea sizeDelta

  1 /*=================================================
  2 *FileName:      SafeAreaPanel.cs 
  3 *Author:        None 
  4 *UnityVersion:  2021.3.20f1 
  5 *Date:          2023-07-20 16:11 
  6 *Description:   UI适配组件
  7 *History:       
  8 *------------------------------------------------
  9 *2023年11月15日17:35:12
 10 *修复获取安全区尺寸的正确数据
 11 *重构适配数据的计算逻辑
 12 *重构全屏显示
 13 *新增RawImg自适应等比缩放(合并脚本)
 14 *重构后适配可根据具体上下左右安全区范围做显示
 15 =================================================*/
 16 using System;
 17 using UnityEngine;
 18 using UnityEngine.UI;
 19 
 20 public class SafeAreaPanel : MonoBehaviour
 21 {
 22     public enum SafeAreaType
 23     {
 24         自适应尺寸,
 25         全屏显示,
 26         /// <summary> 要求所有适配锚点x/y保持一致 </summary>
 27         RawImg自适应等比缩放,
 28     }
 29 
 30     RectTransform RT = null;
 31     private Vector2 m_OlPos;
 32     private RectTransform mParentCanvesRT;
 33     [Header("节点自适应")]
 34     public SafeAreaType m_SafeAreaType;
 35     /// <summary> 屏幕适配UI中心点偏移(ms) </summary>
 36     private Vector2 SafeAreaPanelOffset;
 37 
 38     [HideInInspector] public RawImage rawImage;
 39 
 40     float offsetTop;
 41     float offsetBottom;
 42     float offsetLeft;
 43     float offsetRight;
 44 
 45     ScreenOrientation m_LastScreenOrientation;
 46     bool invokeRefreshFrame = true;
 47     Vector2 lastCanvasSize;
 48 
 49     void OnEnable()
 50     {
 51         if (this == null || this.gameObject == null) return;
 52         if (mParentCanvesRT == null) mParentCanvesRT = GetComponentInParent<CanvasScaler>()?.GetComponent<RectTransform>();
 53         if (mParentCanvesRT == null) return;
 54         if (RT == null) RT = GetComponent<RectTransform>();
 55         if (RT == null) return;
 56         m_OlPos = RT.anchoredPosition;
 57         switch (m_SafeAreaType)
 58         {
 59             case SafeAreaType.自适应尺寸:
 60                 break;
 61             case SafeAreaType.全屏显示:
 62                 break;
 63             case SafeAreaType.RawImg自适应等比缩放:
 64                 if (rawImage == null) rawImage = GetComponent<RawImage>();
 65                 if (rawImage == null) return;
 66                 if (Application.isPlaying)
 67                 {
 68                     Debug.Assert(RT.anchorMax.x == RT.anchorMin.x && RT.anchorMax.x == RT.pivot.x, this);
 69                     Debug.Assert(RT.anchorMax.y == RT.anchorMin.y && RT.anchorMax.y == RT.pivot.y, this);
 70                 }
 71                 break;
 72             default:
 73                 break;
 74         }
 75         AutoSetSafeArea();
 76         Canvas.preWillRenderCanvases += Canvas_preWillRenderCanvases;
 77     }
 78 
 79     private void Canvas_preWillRenderCanvases()
 80     {
 81         if (!lastCanvasSize.Equals(mParentCanvesRT.sizeDelta))
 82         {
 83             lastCanvasSize = mParentCanvesRT.sizeDelta;
 84             invokeRefreshFrame = true;
 85         }
 86         /**
 87          * 渲染顺序为:
 88          *  1.当前帧:设备发生更改屏幕旋转事件,修改了Screen.orientation值
 89          *  2.下一帧:CanvasScaler在Canvas.preWillRenderCanvases 事件里修改Canvas适配sizeDelta
 90          *  preWillRenderCanvases    在即将开始 Canvas 渲染前调用的事件。
 91          *  
 92          *  所以在检测到屏幕旋转事件后,在下一次preWillRenderCanvases事件中进行适配计算
 93          */
 94         if (invokeRefreshFrame)
 95         {
 96             invokeRefreshFrame = false;
 97             AutoSetSafeArea();
 98         }
 99         if (!Screen.orientation.Equals(m_LastScreenOrientation))
100         {
101             invokeRefreshFrame = true;
102             m_LastScreenOrientation = Screen.orientation;
103         }
104     }
105 
106     void OnDisable()
107     {
108         Canvas.preWillRenderCanvases -= Canvas_preWillRenderCanvases;
109     }
110     void AutoSetSafeArea()
111     {
112         offsetTop = Screen.safeArea.yMin / Screen.currentResolution.height;
113         offsetBottom = Screen.safeArea.yMax / Screen.currentResolution.height;
114         offsetLeft = Screen.safeArea.xMin / Screen.currentResolution.width;
115         offsetRight = Screen.safeArea.xMax / Screen.currentResolution.width;
116 
117 
118         switch (m_SafeAreaType)
119         {
120             case SafeAreaType.自适应尺寸:
121                 //安全区域偏移量
122                 RT.anchorMin = new Vector2(offsetLeft, offsetTop);
123                 RT.anchorMax = new Vector2(offsetRight, offsetBottom);
124                 break;
125             case SafeAreaType.全屏显示:
126                 //还原安全区偏移量
127                 RT.anchorMin = RT.anchorMax = new Vector2(0.5f, 0.5f);
128                 RT.sizeDelta = new Vector2(Screen.currentResolution.width, Screen.currentResolution.height);
129 
130                 SafeAreaPanelOffset.x = ((Screen.currentResolution.width - Screen.safeArea.xMax) * 0.5f - Screen.safeArea.xMin * 0.5f) * mParentCanvesRT.sizeDelta.x / Screen.currentResolution.width;
131                 SafeAreaPanelOffset.y = ((Screen.currentResolution.height - Screen.safeArea.yMax) * 0.5f - Screen.safeArea.yMin * 0.5f) * mParentCanvesRT.sizeDelta.y / Screen.currentResolution.height;
132 
133                 RT.anchoredPosition = SafeAreaPanelOffset;
134                 break;
135             case SafeAreaType.RawImg自适应等比缩放:
136                 Vector2 textureSize, rawRtSize;
137                 textureSize = rawRtSize = rawImage.texture == null ? new Vector2(1667, 1024) : new Vector2(rawImage.texture.width, rawImage.texture.height);
138                 if (mParentCanvesRT.sizeDelta.x / mParentCanvesRT.sizeDelta.y < textureSize.x / textureSize.y)
139                 {
140                     rawRtSize.y = mParentCanvesRT.sizeDelta.y;
141                     rawRtSize.x = mParentCanvesRT.sizeDelta.y * textureSize.x / textureSize.y;
142                 }
143                 else
144                 {
145                     rawRtSize.x = mParentCanvesRT.sizeDelta.x;
146                     rawRtSize.y = mParentCanvesRT.sizeDelta.x * textureSize.y / textureSize.x;
147                 }
148 
149                 SafeAreaPanelOffset.x = ((Screen.currentResolution.width - Screen.safeArea.xMax) * RT.anchorMax.x - Screen.safeArea.xMin * (1 - RT.anchorMin.x)) * mParentCanvesRT.sizeDelta.x / Screen.currentResolution.width;
150                 SafeAreaPanelOffset.y = ((Screen.currentResolution.height - Screen.safeArea.yMax) * RT.anchorMax.y - Screen.safeArea.yMin * (1 - RT.anchorMax.y)) * mParentCanvesRT.sizeDelta.y / Screen.currentResolution.height;
151 
152                 RT.sizeDelta = rawRtSize;
153                 RT.anchoredPosition = m_OlPos + SafeAreaPanelOffset;
154                 break;
155             default:
156                 break;
157         }
158 
159     }
160 
161     //#if UNITY_EDITOR || EDITORMODE
162     //    //public bool ShowGUI;
163     //    //private void OnGUI()
164     //    //{
165     //    //    if (!ShowGUI)
166     //    //    {
167     //    //        return;
168     //    //    }
169     //    //    GUIStyle gUIStyle = new GUIStyle();
170     //    //    gUIStyle.normal.textColor = Color.blue;
171     //    //    gUIStyle.fontSize = 20;
172     //    //    GUILayout.Space(100);
173     //    //    GUILayout.Label($"offsetTop: {offsetTop}", gUIStyle);
174     //    //    GUILayout.Label($"offsetBottom: {offsetBottom}", gUIStyle);
175     //    //    GUILayout.Label($"offsetLeft: {offsetLeft}", gUIStyle);
176     //    //    GUILayout.Label($"offsetRight: {offsetRight}", gUIStyle);
177     //    //    GUILayout.Label($"Screen.safeArea.xMin: {Screen.safeArea.xMin}", gUIStyle);
178     //    //    GUILayout.Label($"Screen.safeArea.xMax: {Screen.safeArea.xMax}", gUIStyle);
179     //    //    GUILayout.Label($"Screen.safeArea.yMax: {Screen.safeArea.yMax}", gUIStyle);
180     //    //    GUILayout.Label($"Screen.safeArea.yMin: {Screen.safeArea.yMin}", gUIStyle);
181     //    //    GUILayout.Label($"Screen.currentResolution.width: {Screen.currentResolution.width}", gUIStyle);
182     //    //    GUILayout.Label($"Screen.currentResolution.height: {Screen.currentResolution.height}", gUIStyle);
183     //    //    GUILayout.Label($"SafeAreaPanelOffset: ({SafeAreaPanelOffset.x},{SafeAreaPanelOffset.y})", gUIStyle);
184     //    //    GUILayout.Label($"Screen.orientation: {Screen.orientation}", gUIStyle);
185     //    //    GUILayout.Label($"m_LastScreenOrientation: {m_LastScreenOrientation}", gUIStyle);
186 
187     //    //}
188     //#endif
189 
190 
191 }
View Code

基本完成UGUI适配功能
*Screen.safeArea不支持Android8.0及以下的信息获取,如果需要单独添加设备适配配置
当然也可以跟我一下 忽略。。。
针对折叠屏的适配,暂时可以在Android层添加onConfigurationChanged监听
然后在Unity里面调用一下适配刷新即可

折叠屏的适配-这里同样可以

1 if (!lastCanvasSize.Equals(mParentCanvesRT.sizeDelta))
2         {
3             lastCanvasSize = mParentCanvesRT.sizeDelta;
4             invokeRefreshFrame = true;
5         }

 

标签:RT,适配,Screen,Unity,currentResolution,mParentCanvesRT,UGUI,safeArea,sizeDelta
From: https://www.cnblogs.com/lovewaits/p/17834443.html

相关文章

  • unity 打包问题记录
     问题1: ErrorbuildingPlayerbecausescriptshadcompilererrors问题描述:在打包准备真机测试时发现了这个问题,到处查找解决办法后发现了问题,以下一些解决办法提供了思路。解决思路:(1)、关于AB打包出现的错误:ErrorbuildingPlayerbecausescriptshadcompilererrors的解......
  • Android app的暗黑模式适配实现
    原文地址:Androidapp的暗黑模式适配实现-Stars-One的杂货小窝很久之前放在草稿箱的一篇简单笔记,是之前蓝奏云批量下载工具Android版本实现暗黑主题的适配记录本文所说的这里的暗黑主题,应该只支持Android10系统,不过我手头的Flyme系统(Android9)上测试也有效果,其他低版本......
  • Unity-观察者模式(observer)
    Unity-观察者模式(observer)引言​ 了解完委托(delegate)与事件(event)之后,我们来讨论一个问题。​ 假设我们有一个热水器,我们给他同上电,当水温超过95度的时候:1、扬声器会开始发出语音,告诉你温度;2、液晶屏也会改变水温的显示,来提示水已经烧开了​ 现在我们需要写一个程序来模拟这个......
  • Unity-背包系统
    Unity-背包系统简介​ 背包是每个成功游戏中不可缺少的,玩家获取的装备与道具将会放入背包,需要时再拿出来使用。如果没有背包来储存玩家在游戏中获得的武器和道具,或许游戏将会变得十分单一枯燥,出招方式一成不变。​ 有了背包系统,玩家才可以使用不同的武器,搭配不同的道具,使出不同......
  • Unity-FSM有限状态机
    Unity-FSM有限状态机什么是有限状态机?​ 在编写一些需要判断多个条件的程序时,我们常常会用到if-else语句,这样能够很好的帮我们解决多数问题。但在游戏开发过程中,一个角色的行为不是一成不变的,需要实时的进行修改,此时如果我们使用的是if-else来判断角色所处状态,就需要修改整......
  • Unity-场景的异步加载
    Unity-场景的异步加载为什么需要异步加载​ 在诸多大型游戏里,场景渲染精度都是动态的,随着场景与角色距离的增加,渲染精度也在递减,这样极大的减少了硬件性能的消耗。​ 但如果角色使用了某些传送技能,将自己传送到为渲染的地点,游戏可能就会因为需要瞬间渲染大量的场景而卡顿。此时......
  • Unity-Menu&场景切换
    Unity-Menu&场景切换开始界面1.要创建开始界面,首先要新建一个场景,用于添加游戏开始界面的内容2.新建按钮步骤:UI>画板>Button(按钮)>根据需要设置按钮3.给按钮添加代码,使得按下按钮就可以进入下一关/退出游戏(1)代码内容需要用到usingUnityEngine.SceneManagement的头文件......
  • Unity-敌人(Enemy)
    Unity-敌人(Enemy)引言​ 敌人是每个游戏中不可缺少的部分,设计得好的敌人可以给游戏增添很多乐趣,设计得差的则会非常影响我们的游戏体验。​ 经过这段时间的学习,我们已经接触了非常多的敌人代码的写法,但是就是没有系统的归类,导致每次写敌人,都要从头开始。现在是时候将他们进行一......
  • Unity-Light(含Unity2021-2d项目升级Urp渲染管线)
    Unity-Light(含Unity2021-2d项目升级Urp渲染管线)普通渲染管线(比较老旧的光效升级方式,已舍弃)​ 要使场景和角色拥有光效,那就得让他们先暗下来,给他们添加相应的材质场景材质的添加​ 选中需要添加材质的场景,在右侧框内的“材质”菜单中,选中Default-Diffuse材质人物材质的添加​......
  • Unity-单例模式
    Unity-单例模式前言​ 对于某些特殊的类,我们希望在整个程序的生命周期只创建一个该类的对象,或是希望在其他类没有持有该类的引用,就可以调用该类中的函数,我们就需要将这个类写成单例模式单例的简单实现publicclassTest(){ pubicabstractTestInstance;//创建程序中该......