Unity 2D坐标系转换:适配相机宽高比的视图调整方案
2D游戏:适配相机宽高比的坐标转换方案
针对左上角为原点、坐标范围0-600的2D场景,要让实例化对象不再集中在角落,而是适配相机宽高比,可按以下步骤实现坐标转换:
核心思路
原始坐标是**左上角原点(0,0)**的1:1固定范围(x/y均0-600),需要将其映射到相机的世界空间,同时根据相机宽高比调整,保证内容居中且无拉伸,避免对象扎堆。
步骤1:归一化原始坐标
先把固定范围的(x,y)转换成0-1之间的归一化值,脱离600的固定限制,同时反转y轴(多数游戏引擎的世界空间原点在左下角,和原始坐标的y轴方向相反):
- 归一化x:
normX = x / 600f - 归一化y:
normY = (600f - y) / 600f
步骤2:适配相机宽高比
假设相机的视口高度为camHeight,宽高比为aspectRatio = 相机宽度 / camHeight(不同引擎可通过API获取,比如Unity中正交相机的高度是orthographicSize * 2,宽度则是高度×宽高比)。
根据相机宽高比的不同情况处理:
- 宽屏(aspectRatio > 1):让原始内容的高度填满相机,宽度方向居中留白
- 有效映射范围:以相机高度为基准(保持1:1比例)
- x轴偏移量:
(相机宽度 - camHeight) / 2f - 最终世界x坐标:
offsetX + normX * camHeight - 最终世界y坐标:
normY * camHeight
- 竖屏(aspectRatio < 1):让原始内容的宽度填满相机,高度方向居中留白
- 有效映射范围:以相机宽度为基准(保持1:1比例)
- y轴偏移量:
(camHeight - 相机宽度) / 2f - 最终世界x坐标:
normX * 相机宽度 - 最终世界y坐标:
offsetY + normY * 相机宽度
- 正方形屏幕(aspectRatio = 1):直接将归一化坐标映射到相机视口即可
- 世界x坐标:
normX * 相机宽度 - 世界y坐标:
normY * camHeight
- 世界x坐标:
步骤3:居中对齐优化(可选)
如果要让整个0-600的内容区域完全居中在相机视口,也可以通过“中心偏移”的方式计算:
- 原始区域的中心坐标是(300, 300),对应归一化中心(0.5, 0.5)
- 计算当前相机视口的中心世界坐标:
(相机宽度/2, camHeight/2) - 计算原始坐标相对于中心的偏移:
dx = x - 300,dy = 300 - y(反转y轴) - 根据宽高比计算缩放因子:
- 宽屏/正方形:
scaleFactor = camHeight / 600f - 竖屏:
scaleFactor = 相机宽度 / 600f
- 宽屏/正方形:
- 最终世界坐标:
worldX = 相机宽度/2 + dx * scaleFactorworldY = camHeight/2 + dy * scaleFactor
伪代码示例
// 原始坐标 float originalX = 250f; float originalY = 350f; // 获取相机参数(以Unity为例) Camera mainCam = Camera.main; float camHeight = mainCam.orthographicSize * 2f; float camWidth = camHeight * mainCam.aspect; float aspectRatio = mainCam.aspect; // 归一化并反转y轴 float normX = originalX / 600f; float normY = (600f - originalY) / 600f; float worldX, worldY; // 适配宽高比 if (aspectRatio > 1f) { float effectiveSize = camHeight; float offsetX = (camWidth - effectiveSize) / 2f; worldX = offsetX + normX * effectiveSize; worldY = normY * effectiveSize; } else if (aspectRatio < 1f) { float effectiveSize = camWidth; float offsetY = (camHeight - effectiveSize) / 2f; worldX = normX * effectiveSize; worldY = offsetY + normY * effectiveSize; } else { worldX = normX * camWidth; worldY = normY * camHeight; } // 输出转换后的坐标 Debug.Log($"转换后世界坐标:({worldX}, {worldY})");
内容的提问来源于stack exchange,提问作者aokde
相关产品推荐
相关产品推荐

