Unity实现屏幕黑边--游戏画面和UI异形屏处理(安全区渲染)

在手机上,如果想以黑边形式显示游戏画面,比如显示区域避开异形屏、水滴屏那一行。有很多种思路,最后觉得下面这种方法比较简单合适,下面分享一下。

方法:需要分别处理,游戏画面黑边、UI黑边:

1,游戏画面黑边----主相机+临时Canvas

【主相机】

挂上如下脚本 M_Cam_SafeArea.cs:

using UnityEngine;


// 处理游戏画面的安全区渲染, 挂在主相机上即可 
public class M_Cam_SafeArea : MonoBehaviour
{
    // 用于产生黑边固定色的临时canvas
    public GameObject blackCanvas_pref;
    public int frame_num = 0;
    private Rect lastSafeArea = new Rect(0, 0, 0, 0);
    private Camera mainCamera;
    private GameObject blackCanvas;


    void Awake()
    {
        mainCamera = Camera.main;
        ApplySafeArea();
        // 专门生成初始黑边的canvas
        blackCanvas = Instantiate(blackCanvas_pref);
    }


    void Update()
    {
        /*
        // 也可以每帧检测,如果安全区发生变化则更新布局
        if (lastSafeArea != Screen.safeArea)
        {
            ApplySafeArea();
        }
        */
        frame_num += 1; 
        // 得是第2帧以后, 删除专用黑边canvas才行。以清除第一帧渲染的残留
        if (frame_num == 2)
        {
            Destroy(blackCanvas);
        } 
    }


    void ApplySafeArea()
    {
        Rect safeArea = Screen.safeArea;
        // 计算安全区的归一化坐标
        float xMin = safeArea.x / Screen.width;
        float yMin = safeArea.y / Screen.height;
        float xMax = (safeArea.x + safeArea.width) / Screen.width;
        float yMax = (safeArea.y + safeArea.height) / Screen.height;
        // 设置相机的视口,使内容位于安全区内
        // width, height, x(距离屏幕左边缘), y()
        mainCamera.rect = new Rect(xMin, yMin, xMax - xMin, yMax - yMin);
        lastSafeArea = safeArea;
    }
}

【临时Canvas】

默认的canvas即可。然后新建一个可以铺满屏幕的image。

image,可以自定义你想要的“黑边“”颜色。比如红色(下面用红色,以免黑边在模拟器里看不清界限)。

制作好黑边canvas后,把其拖入主相机的M_Cam_SafeArea脚本的对应属性栏里:

OK,我们运行一下,看看效果(注意,运行后1帧,这个黑边canvas就被销毁了):

2,UI黑边(UI只在安全区渲染)

再新建一个Canvas,这个就是游戏逻辑用的Canvas了,渲染模式为SSO模式的(如果是SSC,也就是3D相机的话,就可以直接走主相机了):

新建一个UI元素,名为SafeArea。

设置如下(四边角适应,并挂接下面要写的脚本):

UI_SafeArea.cs脚本:

using UnityEngine;


public class UI_SafeArea : MonoBehaviour
{
    RectTransform rectTransform;
    Rect safeArea;
    Vector2 minAnchor;
    Vector2 maxAnchor; 
    
    void Awake()
    {
        rectTransform = GetComponent<RectTransform>();
        safeArea = Screen.safeArea;
        Debug.Log(Screen.height + "*" + Screen.width); 
        Debug.Log(safeArea);
        minAnchor = safeArea.position;
        maxAnchor = minAnchor + safeArea.size;

        minAnchor.x /= Screen.width;
        minAnchor.y /= Screen.height;
        maxAnchor.x /= Screen.width;
        maxAnchor.y /= Screen.height;

        rectTransform.anchorMin = minAnchor;
        rectTransform.anchorMax = maxAnchor; 
    }
}

好。到此UI的安全区就设置完毕了。游戏中需要的UI,放入SafeArea节点下,即可。

【完整试验】

比如,下面我们放入2个元素,一个文本,在上中位置。一个图片,在左下位置:

运行,看看不同机型的效果, OK, 完美匹配:

ps. 额外引申:

如果需要固定显示宽高比,然后黑白显示,参考这个:

https://www.youtube.com/watch?v=PClWqhfQlpU

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值