Unity移动端不同分辨率下画面两侧裁剪(非Canvas相关)修复方法
Unity 3D竖屏游戏多分辨率适配修复方案
问题根因
该问题和Canvas设置无关,核心是相机视锥体宽高比未做多分辨率适配:
开发阶段使用的1080×1920为标准9:16比例,而部署的1080×2340设备为9:19.5的窄长屏比例。如果相机视口默认锁定纵向可视范围,横向可视范围会随宽高比变小被压缩,直接导致开发阶段可见的两侧内容被裁剪;硬编码的屏幕移动边界不会随分辨率变化更新,就会出现玩家能移动到可视区域外的问题。
分步修复操作
1. 挂载相机适配脚本,从根源解决内容裁剪
根据你使用的相机类型,把对应脚本挂到主相机上,以开发分辨率为基准动态调整视口范围,优先保证横向内容完整不裁剪,纵向多出的区域做自然延伸:
正交相机适配(固定视角3D/2.5D游戏通用)
using UnityEngine; [ExecuteAlways] public class CameraAspectFitter : MonoBehaviour { // 开发阶段基准分辨率 private const float DesignWidth = 1080f; private const float DesignHeight = 1920f; // 填你开发阶段调试好的正交相机Size值 public float baseOrthoSize = 5f; private Camera _mainCam; private int _lastScreenWidth, _lastScreenHeight; private void Awake() { _mainCam = GetComponent<Camera>(); FitCameraViewport(); } private void Update() { // 分辨率变化时自动重适配(适配折叠屏、窗口大小调整场景) if (_lastScreenWidth != Screen.width || _lastScreenHeight != Screen.height) { FitCameraViewport(); } } private void FitCameraViewport() { _lastScreenWidth = Screen.width; _lastScreenHeight = Screen.height; float designAspect = DesignWidth / DesignHeight; float currentAspect = (float)Screen.width / Screen.height; // 窄长屏放大正交Size,保证横向内容不被裁剪 if (currentAspect < designAspect) { _mainCam.orthographicSize = baseOrthoSize * (designAspect / currentAspect); } else { // 宽屏保持基准Size,两侧内容自然延伸 _mainCam.orthographicSize = baseOrthoSize; } } /// <summary> /// 获取当前分辨率下相机在指定平面的可视边界,用于玩家移动限制 /// </summary> public Bounds GetVisibleWorldBounds(float targetPlaneZ = 0f) { float camDistance = Mathf.Abs(targetPlaneZ - transform.position.z); Vector3 minPoint = _mainCam.ScreenToWorldPoint(new Vector3(0, 0, camDistance)); Vector3 maxPoint = _mainCam.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, camDistance)); Bounds visibleBounds = new Bounds(); visibleBounds.SetMinMax(minPoint, maxPoint); return visibleBounds; } }
透视相机适配
如果使用透视相机,把上述脚本中修改orthographicSize的逻辑替换为修改fieldOfView即可,baseOrthoSize字段替换为你开发阶段调好的基准FOV值,适配逻辑完全一致。
2. 动态计算玩家移动边界,禁止硬编码
删除玩家控制脚本中写死的屏幕边界坐标,每次玩家移动前调用上述脚本的GetVisibleWorldBounds方法,获取当前分辨率下的真实可视边界,用数值钳制方法限制玩家移动范围:
// 玩家移动脚本中的边界限制示例 public class PlayerMovement : MonoBehaviour { [SerializeField] private CameraAspectFitter mainCamFitter; [SerializeField] private float moveSpeed = 5f; private Bounds _visibleBounds; private void Start() { _visibleBounds = mainCamFitter.GetVisibleWorldBounds(transform.position.z); } private void Update() { // 读取移动输入 float moveX = Input.GetAxis("Horizontal"); float moveY = Input.GetAxis("Vertical"); Vector3 targetPos = transform.position + new Vector3(moveX, moveY, 0) * moveSpeed * Time.deltaTime; // 限制玩家在可视范围内 targetPos.x = Mathf.Clamp(targetPos.x, _visibleBounds.min.x, _visibleBounds.max.x); targetPos.y = Mathf.Clamp(targetPos.y, _visibleBounds.min.y, _visibleBounds.max.y); transform.position = targetPos; } }
3. 长屏场景兜底适配
窄长屏设备上下会比基准分辨率多出一部分可视区域,做两个简单调整避免穿帮:
- 把场景地面、远景背景板的纵向长度拉长25%~30%,覆盖当前市面上最长的9:21比例竖屏设备
- 关键关卡触发点、可收集道具不要贴场景上下边缘摆放,避免短屏设备上元素超出可视范围
注意事项
- 不要在Player Settings中开启固定分辨率缩放,不要手动修改相机的
Viewport Rect参数,避免覆盖脚本适配逻辑 - 编辑器下可直接切换Game视图分辨率,测试1080×1920、1080×2340、720×1280等主流竖屏分辨率,确认两侧无裁剪、玩家不会跑出可视区即可打包测试
内容的提问来源于stack exchange,提问作者guilherme coelho
相关产品推荐
相关产品推荐

