FairyGUI-Unity 异形屏适配
本文中会修改到FairyGUI源代码,涉及两个文件Stage和StageCamera,需要对Unity的屏幕类了解。
在网上查找有很多的异形屏适配操作,但对于FairyGUI相关的描述操作很少,这里我贴出一下自己在实际应用中的异形屏UI适配操作。
原理
获取当前设备的屏幕安全区域并设置为UI的正常显示尺寸,通过屏幕安全区域和实际分辨率修改UI背景的位置和尺寸。注意UI在设计中将溢出处理设置为默认“可见”。
关键方法:SetXY(x,y);SetSize(width,height)
打开Stage脚本,在构造函数中找到方法:
SetSize(Screen.width, Screen.height)
通过方法可以看到默认直接设置屏幕的宽高,将其修改为屏幕安全区域的宽高,这里我做了对称处理:
var safeArea = Screen.safeArea;
int safeAreaWidth = Mathf.CeilToInt(safeArea.width - safeArea.x);
int safeAreaHeight = safeArea.height;
SetSize(safeAreaWidth, safeAreaHeight);
打开StageCamera脚本,将OnEnable方法中的默认屏幕尺寸修改为安全区域的尺寸。
OnScreenSizeChanged(Screen.width, Screen.height);
修改为:
OnScreenSizeChanged(_safeAreaWidth, _safeAreaHeight);
将Update中的屏幕分辨率检测也一同修改为安全区域分辨率检测:
if (screenWidth != Screen.width || screenHeight != Screen.height)OnScreenSizeChanged(Screen.width, Screen.height);
修改为:
if (screenWidth != _safeAreaWidth || screenHeight != _safeAreaHeight)OnScreenSizeChanged(_safeAreaWidth, _safeAreaHeight);
之后在UI界面中,将背景的位置和大小修改为屏幕实际分辨率和安全区域外的位置。
SetXY(-Screen.safeArea.x,Screen.safeArea.y)
SetSize(Screen.width,Screen.height)
完整代码参考
Stage修改后的构造方法
/// <summary>
///
/// </summary>
public Stage(): base()
{_inst = this;soundVolume = 1;_updateContext = new UpdateContext();_frameGotHitTarget = -1;_touches = new TouchInfo[5];for (int i = 0; i < _touches.Length; i++)_touches[i] = new TouchInfo();bool isOSX = Application.platform == RuntimePlatform.OSXPlayer|| Application.platform == RuntimePlatform.OSXEditor;if (Application.platform == RuntimePlatform.WindowsPlayer|| Application.platform == RuntimePlatform.WindowsEditor|| isOSX)touchScreen = false;elsetouchScreen = Input.touchSupported && SystemInfo.deviceType != DeviceType.Desktop;//在PC上,是否retina屏对输入法位置,鼠标滚轮速度都有影响,但现在没发现Unity有获得的方式。仅判断是否Mac可能不够(外接显示器的情况)。所以最好自行设置。devicePixelRatio = (isOSX && Screen.dpi > 96) ? 2 : 1;_rollOutChain = new List<DisplayObject>();_rollOverChain = new List<DisplayObject>();_focusOutChain = new List<DisplayObject>();_focusInChain = new List<DisplayObject>();_focusHistory = new List<Container>();_cursors = new Dictionary<string, CursorDef>();//根据开关修改UI实际的分辨率if (GF.Main.Inst.enableSafeArea)//加一个启用安全区的开关{var safeArea = Screen.safeArea;int safeAreaWidth = Mathf.CeilToInt(safeArea.width - safeArea.x);int safeAreaHeight = Mathf.CeilToInt(safeArea.height + safeArea.y);SetSize(safeAreaWidth, safeAreaHeight);}elseSetSize(Screen.width, Screen.height);this.cachedTransform.localScale = new Vector3(StageCamera.DefaultUnitsPerPixel, StageCamera.DefaultUnitsPerPixel, StageCamera.DefaultUnitsPerPixel);StageEngine engine = GameObject.FindObjectOfType<StageEngine>();if (engine != null)UnityEngine.Object.Destroy(engine.gameObject);this.gameObject.name = "Stage";this.gameObject.layer = LayerMask.NameToLayer(StageCamera.LayerName);this.gameObject.AddComponent<StageEngine>();this.gameObject.AddComponent<UIContentScaler>();this.gameObject.SetActive(true);UnityEngine.Object.DontDestroyOnLoad(this.gameObject);EnableSound();Timers.inst.Add(5, 0, RunTextureCollector);SceneManager.sceneLoaded += SceneManager_sceneLoaded;
}
StageCamera的修改后完整代码
private Rect _safeArea;
private int _safeAreaWidth, _safeAreaHeight;
void OnEnable()
{_safeArea = Screen.safeArea;_safeAreaWidth = Mathf.CeilToInt(_safeArea.width - _safeArea.x);_safeAreaHeight = _safeArea.height;cachedTransform = this.transform;cachedCamera = this.GetComponent<Camera>();if (this.gameObject.name == Name){main = cachedCamera;isMain = true;}if (Display.displays.Length > 1 && cachedCamera.targetDisplay != 0 && cachedCamera.targetDisplay < Display.displays.Length)_display = Display.displays[cachedCamera.targetDisplay];if (_display == null){if (GF.Main.Inst.enableSafeArea)//加一个启用安全区的开关{OnScreenSizeChanged(_safeAreaWidth, _safeAreaHeight);}elseOnScreenSizeChanged(Screen.width, Screen.height);}elseOnScreenSizeChanged(_display.renderingWidth, _display.renderingHeight);
}
void Update()
{if (_display == null){if (GF.Main.Inst.enableSafeArea)//加一个启用安全区的开关{if (screenWidth != _safeAreaWidth || screenHeight != _safeAreaHeight)OnScreenSizeChanged(_safeAreaWidth, _safeAreaHeight);}else{if (screenWidth != Screen.width || screenHeight != Screen.height)OnScreenSizeChanged(Screen.width, Screen.height);}}else{if (screenWidth != _display.renderingWidth || screenHeight != _display.renderingHeight)OnScreenSizeChanged(_display.renderingWidth, _display.renderingHeight);}
}
UI界面中设置背景组件名为“_Loader_Bg”的位置和大小。注意UI在设计中将溢出处理设置为默认“可见”。
if ( _Loader_Bg != null)
{_Loader_Bg.SetXY(-Screen.safeArea.x,Screen.safeArea.y);_Loader_Bg.SetSize(Screen.width,Screen.height);
}
以上是对FairyGUI在设计横版游戏时对异形屏的适配操作,竖版游戏也是同理操作。如果对你有帮助,那就好!有问题也可以留言指出!感谢!
相关文章:
FairyGUI-Unity 异形屏适配
本文中会修改到FairyGUI源代码,涉及两个文件Stage和StageCamera,需要对Unity的屏幕类了解。 在网上查找有很多的异形屏适配操作,但对于FairyGUI相关的描述操作很少,这里我贴出一下自己在实际应用中的异形屏UI适配操作。 原理 获…...

Oracle监听器启动出错:本地计算机上的OracleOraDb11g_home1TNSListener服务启动后又停止了解决方案
在启动oracle的服务OracleOraDb11g_home1TNSListener时,提示服务启动后又停止了。 解决方法: 修改oracle安装目录下的两个配置文件: 以上两个文件,对应的HOST的值,都改为127.0.0.1 然后再启动服务,启动成…...
Spring复习:(58)<context:annotation-config/>的作用
引入如下的BeanPostProcessor • ConfigurationClassPostProcessor • AutowiredAnnotationBeanPostProcessor • CommonAnnotationBeanPostProcessor • PersistenceAnnotationBeanPostProcessor • EventListenerMethodProcessor如果xml文件配置了bean中使用了Autowired注解…...

“东方杯”英特尔oneAPI黑客松大赛—参赛经验分享
目录 前言1、大赛要求2、oneMKL介绍3、准备 oneMKL基本使用1、下载:2、安装:3、初始化oneMKL环境:4、编译代码5、运行 所需的头文件使用oneMKL工具生成随机数使用fftw3计算FFT调用oneMKL API加速计算FFT对比两种方法的准确性输出结果结束语 前…...

win10家庭版远程桌面补丁_rdp wrapper
RDP Wrapper Library 就是可以帮你在 Windows 7、Windows 8、Windows 10 家庭版中打开远程桌面的工具。 1、把电脑上打开的安全软件与杀毒软件都关掉,因为这个远程桌面补丁会修改系统文件,所以安全软件可能会拦截。 2、下载RDP Wrapper Library补丁压缩…...
【C++设计模式】开放-封闭原则
2023年8月27日,周日下午 我觉得我的这篇博客还是写得很不错的,哈哈哈。 目录 概述举例说明用开放-封闭原则重构 概述 开放-封闭原则(Open-Closed Principle,OCP)是面向对象设计中的一个重要原则,也是许多…...

vue+file-saver+xlsx+htmlToPdf+jspdf实现本地导出PDF和Excel
页面效果如下(echarts图表按需添加,以下代码中没有) 1、安装插件 npm install xlsx --save npm install file-saver --save npm install html2canvas --save npm install jspdf --save2、main.js引入html2canvas import htmlToPdf from …...

axios 进阶
axios 进阶 接口传参方式 使用 xhr 原生技术或者是 axios 时,它的 post 传参方式是键值对的形式 keyvalue。但是在实际开发中一般是使用对象的形式定义数据,方便读取和赋值。所以当我们需要发起请求时可以通过 qs 这一款插件将对象转成键值对形式&…...

Redis限流实践:实现用户消息推送每天最多通知2次的功能
🏆作者简介,黑夜开发者,CSDN领军人物,全栈领域优质创作者✌,CSDN博客专家,阿里云社区专家博主,2023年6月CSDN上海赛道top4。 🏆数年电商行业从业经验,历任核心研发工程师…...
uniapp 存储base64资源为http链接图片
1. 新建一个base64.js 文件 const fsm wx.getFileSystemManager(); // base64data base64资源 // name 文件名 function base64src(base64data, name, cb) {const time new Date().getTime();const filePath ${wx.env.USER_DATA_PATH}/${name}.${time}.png;const buffer …...
列表类控件虚拟化
WPF列表控件提供的最重要的功能是UI虚拟化(WPF编程宝典说的)。所有的WPF列表控件(所有继承自ItemsControl的控件,包括ListBox、CombBox、ListView、TreeView、DataGrid)都支持UI虚拟化。 UI虚拟化的支持实际上没有被构…...
c# 多线程Task.Run 取消正在执行的多线程
c# 异步处理,上次处理没有完成,下次有紧接着处理多线程出错 在 C# 中进行异步处理时,确保处理上一个任务完成后再处理下一个任务是很重要的,特别是在涉及多线程的情况下。如果上一个任务尚未完成,而下一个任务又开始执…...
sql server 如何设置主键
开始之前 限制和局限 一个表只能包含一个 PRIMARY KEY 约束。 在 PRIMARY KEY 约束中定义的所有列都必须定义为 NOT NULL。 如果没有指定为 Null 性,则加入 PRIMARY KEY 约束的所有列的为 Null 性都将设置为 NOT NULL。 创建主键会自动创建相应的唯一群集索引、…...

【LeetCode-中等题】19. 删除链表的倒数第 N 个结点
文章目录 题目方法一:节点加入集合找索引方法二:直接计算长度,然后找出要删除的节点的前一个节点方法三:栈方法四:前后双指针 题目 这题的关键在与两个点 一定要设置一个哑结点,防止删除第一个元素时,导致空…...

Matlab图像处理-减法运算
减法运算 图像减法也称为差分方法,是一种常用于检测图像变化及运动物体的图像处理方法。常用来检测一系列相同场景图像的差异,其主要的应用在于检测同一场景下两幅图像之间的变化或是混合图像的分离。 差影法 将同一景物在不同时问拍摄的图像或同一景…...

stm32之11.USART串口通信
可以添加上拉电阻,但会增加功耗,传输距离变长 要添加库函数USART 官方参考文档说明书位置 ALT+左键可实现整体删除(如下图) 输出模式第三种模式AF ---------------------- 源码 远程控制pc端 #include <stm32f4x…...

Python实现T检验
今天来分享一下T检验的python实现方法。 01 先来上一波概念。 1.单样本t检验,又称单样本均数t检验,适用于来自正态分布的某个样本均数与已知总体均数的比较,其比较目的是检验样本均数所代表的总体均数是否与已知总体均数有差别。已知总体均数…...

校招算法题实在不会做,有没有关系?
文章目录 前言一、校招二、时间复杂度1、单层循环2、双层循环 三、空间复杂度四、数据结构五、校招算法题实在不会做,有没有关系?六、英雄算法集训 前言 英雄算法联盟八月集训 已经接近尾声,九月算法集训将于 09月01日 正式开始,目…...

Michael.W基于Foundry精读Openzeppelin第32期——SignatureChecker.sol
Michael.W基于Foundry精读Openzeppelin第32期——SignatureChecker.sol 0. 版本0.1 SignatureChecker.sol 1. 目标合约2. 代码精读2.1 isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) 0. 版本 [openzeppelin]:v4.8.3,[for…...

如何修改字符串内容?
⭐ 作者:小胡_不糊涂 🌱 作者主页:小胡_不糊涂的个人主页 📀 收录专栏:浅谈Java 💖 持续更文,关注博主少走弯路,谢谢大家支持 💖 String 1. 修改字符串2. StringBuilder和…...

手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...

【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...

算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...