在手机上,如果想以黑边形式显示游戏画面,比如显示区域避开异形屏、水滴屏那一行。有很多种思路,最后觉得下面这种方法比较简单合适,下面分享一下。
方法:需要分别处理,游戏画面黑边、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. 额外引申:
如果需要固定显示宽高比,然后黑白显示,参考这个: