FairyGUI-Unity 异形屏适配

本文中会修改到FairyGUI源代码,涉及两个文件Stage和StageCamera,需要对Unity的屏幕类了解。

在网上查找有很多的异形屏适配操作,但对于FairyGUI相关的描述操作很少,这里我贴出一下自己在实际应用中的异形屏UI适配操作。

原理

获取当前设备的屏幕安全区域并设置为UI的正常显示尺寸,通过屏幕安全区域和实际分辨率修改UI背景的位置和尺寸。注意UI在设计中将溢出处理设置为默认"可见"。

关键方法:SetXY(x,y);SetSize(width,height)

打开Stage脚本,在构造函数中找到方法:

cs 复制代码
SetSize(Screen.width, Screen.height)

通过方法可以看到默认直接设置屏幕的宽高,将其修改为屏幕安全区域的宽高,这里我做了对称处理:

cs 复制代码
var safeArea = Screen.safeArea;
int safeAreaWidth = Mathf.CeilToInt(safeArea.width - safeArea.x);
int safeAreaHeight = safeArea.height;
SetSize(safeAreaWidth, safeAreaHeight);

打开StageCamera脚本,将OnEnable方法中的默认屏幕尺寸修改为安全区域的尺寸。

cs 复制代码
OnScreenSizeChanged(Screen.width, Screen.height);

修改为:

cs 复制代码
OnScreenSizeChanged(_safeAreaWidth, _safeAreaHeight);

将Update中的屏幕分辨率检测也一同修改为安全区域分辨率检测:

cs 复制代码
if (screenWidth != Screen.width || screenHeight != Screen.height)
    OnScreenSizeChanged(Screen.width, Screen.height);

修改为:

cs 复制代码
if (screenWidth != _safeAreaWidth || screenHeight != _safeAreaHeight)
    OnScreenSizeChanged(_safeAreaWidth, _safeAreaHeight);

之后在UI界面中,将背景的位置和大小修改为屏幕实际分辨率和安全区域外的位置。

Lua 复制代码
SetXY(-Screen.safeArea.x,Screen.safeArea.y)
SetSize(Screen.width,Screen.height)

完整代码参考

Stage修改后的构造方法

cs 复制代码
/// <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;
    else
        touchScreen = 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);
    }
    else
        SetSize(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的修改后完整代码

cs 复制代码
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);
        }else
            OnScreenSizeChanged(Screen.width, Screen.height);
    }
    else
        OnScreenSizeChanged(_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在设计中将溢出处理设置为默认"可见"。

cs 复制代码
if ( _Loader_Bg != null)
{
    _Loader_Bg.SetXY(-Screen.safeArea.x,Screen.safeArea.y);
    _Loader_Bg.SetSize(Screen.width,Screen.height);
}

以上是对FairyGUI在设计横版游戏时对异形屏的适配操作,竖版游戏也是同理操作。如果对你有帮助,那就好!有问题也可以留言指出!感谢!

相关推荐
神码编程3 小时前
【Unity功能集】TextureShop纹理工坊(五)选区
unity·游戏引擎·shader·ps选区
m0_748251728 小时前
Android webview 打开本地H5项目(Cocos游戏以及Unity游戏)
android·游戏·unity
benben0449 小时前
Unity3D仿星露谷物语开发7之事件创建动画
unity·游戏引擎
林枫依依11 小时前
Unity2021.3.16f1可以正常打开,但是Unity2017.3.0f3却常常打开闪退或者Unity2017编辑器运行起来就闪退掉
unity
异次元的归来1 天前
Unity DOTS中的share component
unity·游戏引擎
向宇it1 天前
【从零开始入门unity游戏开发之——C#篇25】C#面向对象动态多态——virtual、override 和 base 关键字、抽象类和抽象方法
java·开发语言·unity·c#·游戏引擎
_oP_i1 天前
unity webgl部署到iis报错
unity
Go_Accepted1 天前
Unity全局雾效
unity
向宇it1 天前
【从零开始入门unity游戏开发之——C#篇24】C#面向对象继承——万物之父(object)、装箱和拆箱、sealed 密封类
java·开发语言·unity·c#·游戏引擎
每日出拳老爷子1 天前
【图形渲染】【Unity Shader】【Nvidia CG】有用的参考资料链接
unity·游戏引擎·图形渲染