FairyGUI-Unity special-shaped screen adaptation

This article will modify the FairyGUI source code, involving two files Stage and StageCamera, which requires understanding of Unity's screen class.

There are many special-shaped screen adaptation operations found on the Internet, but there are very few description operations related to FairyGUI. Here I post my own special-shaped screen UI adaptation operations in practical applications.

principle

Get the screen safe area of ​​the current device and set it to the normal display size of the UI. Modify the position and size of the UI background through the screen safe area and actual resolution. Note that the UI is designed with overflow handling set to "visible" by default.

Key methods: SetXY(x,y);SetSize(width,height)

Open the Stage script and find the method in the constructor:

SetSize(Screen.width, Screen.height)

Through the method, you can see that the width and height of the screen are directly set by default and modified to the width and height of the safe area of ​​the screen. Here I have done symmetrical processing:

var safeArea = Screen.safeArea;
int safeAreaWidth = Mathf.CeilToInt(safeArea.width - safeArea.x);
int safeAreaHeight = safeArea.height;
SetSize(safeAreaWidth, safeAreaHeight);

Open the StageCamera script and change the default screen size in the OnEnable method to the size of the safe area.

OnScreenSizeChanged(Screen.width, Screen.height);

change into:

OnScreenSizeChanged(_safeAreaWidth, _safeAreaHeight);

 Also modify the screen resolution detection in Update to safe area resolution detection:

if (screenWidth != Screen.width || screenHeight != Screen.height)
    OnScreenSizeChanged(Screen.width, Screen.height);

change into:

if (screenWidth != _safeAreaWidth || screenHeight != _safeAreaHeight)
    OnScreenSizeChanged(_safeAreaWidth, _safeAreaHeight);

Then in the UI interface, modify the position and size of the background to a position outside the actual resolution of the screen and the safe area.

SetXY(-Screen.safeArea.x,Screen.safeArea.y)
SetSize(Screen.width,Screen.height)

Full code reference

Stage modified construction method
/// <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;
}
The modified complete code of 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);
        }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);
    }
}

Set the position and size of the background component named "_Loader_Bg" in the UI interface. Note that the UI is designed with overflow handling set to "visible" by default.

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

The above is the adaptation operation of FairyGUI to special-shaped screens when designing horizontal games. The same operation is done for vertical games. If it helps you, great! If you have any questions, you can leave a message! grateful!

Guess you like

Origin blog.csdn.net/u012433546/article/details/132447965