目录
宽度不变策略
高度不变策略
宽度不变策略
开发分辨率 750*1334 (宽高比:0.56)
真机分辨率 1170*2532 (宽高比:0.46)
真机宽高比<开发宽高比,采用宽度不变策略
理由:小于代表真机高度比开发高度更大,因此不需要担心高度上的遮挡,而应担心宽度的遮挡,为了避免宽度上有遮挡问题,因此保证宽度不变策略;
左图是开发分辨率下的情况(宽度和高度均正常 设计上就是如此)
右图是真机分辨率下适配后的情况,保证宽度不变(可见宽度上的绿色边缘处是紧贴着屏幕边缘),但是高度绿色边缘没有紧贴白色的UI(问题1)(下面的一行白色是UGUI UGUI紧贴着屏幕底下边缘)
不启用适配状况:若不启用摄像机适配会呈现如下图:
宽度会被遮挡一部分!因此我们要保证宽度不变
问题1(高度绿色边缘没有紧贴白色的UI)解决思路:
将整个3D场景所有元素放于一个根节点下,往下移动一定距离来紧贴白色UI
移动的相对距离是 (适配后的摄像机size - 开发时摄像机size),移动后得到如下图
注意相对的是指摄像机空间下的相对距离(Y轴,即上下位移)
如下脚本挂载摄像机下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class CameraAdapt : MonoBehaviour
{
//开发宽度
private int width = 750;
//开发高度
private int height = 1334;
//摄像机原始size
private float cameraSize;
//场景物体根节点
public Transform levelTrans;
//CanvasScaler组件
public CanvasScaler canvasScaler;
//场景物体根节点世界位置
Vector3 levelWorldPos;
void Start()
{
//记录原始大小
cameraSize = GetComponent<Camera>().orthographicSize;
//场景世界位置
levelWorldPos = levelTrans.position;
AdaptCamera();
}
private void AdaptCamera()
{
Camera camera = Camera.main;
float devRate = (750f / 1334f);
float nowRate = (Screen.width * 1.0f / Screen.height);
Debug.Log("开发宽高比:" + devRate);
Debug.Log("真机宽高比:" + nowRate);
//真机宽高比 > 开发宽高比时 , 例如 0.75 > 0.56 (目前是0.56) 说明真机更倾向高度不变策略 少于时更倾向宽度不变
bool useHeight = false;
if (nowRate > devRate)
{
useHeight = true; //你可尝试注释这一行来查看ipad之类的适配情况,如果依旧保持宽度不变 会发生某些场景物体可能会因高度变小而无法看到。
}
Debug.Log("Screen.width :" + Screen.width);
Debug.Log("Screen.height :" + Screen.height);
float changeRate = (width * 1.0f / height) * (Screen.height * 1.0f / Screen.width);
Debug.Log(changeRate);
//保证高度不变
if (useHeight)
{
//原Unity策略就是高度不变,所以不需要任何算法,直接保持原样即可(这里cameraSize就是原始size)
float targetHeight = cameraSize;
camera.orthographicSize = targetHeight;
//修改Canvas的适配为高度不变策略
canvasScaler.matchWidthOrHeight = 1;
}
else
{
//保证宽度不变
float targetWidth = cameraSize * (width * 1.0f / height);
camera.orthographicSize = targetWidth * (Screen.height * 1.0f / Screen.width);
//修改Canvas的适配为宽度不变策略
canvasScaler.matchWidthOrHeight = 0;
//在宽度不变情况下,拉长高度而导致场景空白区域变多后,将场景元素向下对齐的方案
//即真机摄像机单位高度值 - 开发单位高度值 = 单位高度差值
float deltaHeight = camera.orthographicSize - cameraSize;
Debug.Log("camera.orthographicSize:" + camera.orthographicSize + ",cameraSize:" + cameraSize + ",deltaHeight:" + deltaHeight);
//重置场景根节点世界坐标
levelTrans.position = levelWorldPos;
//延迟3秒后再偏移,目的是为了看到这个过程是如何变化让场景向下对齐
StartCoroutine(DelayToSetPos(deltaHeight));
}
}
IEnumerator DelayToSetPos(float deltaHeight)
{
yield return new WaitForSeconds(1f);
//场景根节点世界坐标 转 位于摄像机下的局部坐标
Vector3 levelLocalPos = this.transform.InverseTransformPoint(levelWorldPos);
//进行高度偏移 (高度单位差) 即向下对齐
levelLocalPos = new Vector3(levelLocalPos.x, levelLocalPos.y - deltaHeight, levelLocalPos.z);
// 位于摄像机下的局部坐标 转 世界坐标 赋予场景根节点
levelTrans.position = this.transform.TransformPoint(levelLocalPos);
}
// Update is called once per frame
void Update()
{
//按下空格即可再次适配 (可以动态改Game 分辨率 测试不同分辨率下的情况)
if (Input.GetKeyDown(KeyCode.Space))
{
AdaptCamera();
}
}
}
其他场景信息:
高度不变策略
当真机宽高比 > 开发宽高比时,采用高度不变策略
主要变化就是Canvas Scaler,摄像机size是保持不变的,Unity原本就是高度不变策略。
如果不采用高度不变策略会得到如下图,高度上会有场景元素被遮挡!
注释一行即可测试