最新文章
Cocos2d-x游戏开发实例详解7:对象释放时机
03-25 13:59
Cocos2d-x游戏开发实例详解6:自动释放池
03-25 13:55
Cocos2d-x游戏开发实例详解5:神奇的自动释放
03-25 13:49
Cocos2d-x游戏开发实例详解4:游戏主循环
03-25 13:44
Cocos2d-x游戏开发实例详解3:无限滚动地图
03-25 13:37
Cocos2d-x游戏开发实例详解2:开始菜单续
03-25 13:32
Unity 窗口适配
在当今的开发环境中,设备类型繁多,尤其是安卓设备,仅手机就可能存在多种不同的分辨率,更不用说平板设备了。即便苹果设备的分辨率种类相对较少,但自 iPhone 6 发布以来,其分辨率类型也有所增加。因此,实现 Unity 窗口适配成为了开发过程中的一项重要任务。下面将分享一个 Unity 屏幕适配方案,供大家参考学习。
适配方案概述
在 Unity 中,屏幕适配一直没有一个完美的解决方案。为了方便开发者在编辑器模式下调整 UI 位置,并在运行时实现自动对齐,我们编写了一个在编辑器模式下运行的类。该方案通过根据象限划分 UI 的位置,实现不同分辨率下的自动调整,开发者无需设置任何属性,只需将脚本附加到物体上即可。
代码实现
以下是具体的代码实现,文件名为 AutoLayout.cs:
using UnityEngine;
using System.Collections;
// 定义象限布局枚举
public enum QuadrantLayout
{
Quadrant1,
Quadrant2,
Quadrant3,
Quadrant4
}
// 该脚本在编辑器模式下执行,并添加到组件菜单中
[ExecuteInEditMode]
[AddComponentMenu("Auto Layout #0")]
public class AutoLayout : MonoBehaviour
{
// UI 相机
Camera uiCamera;
// 象限布局
QuadrantLayout quadrant;
// 边距
Vector2 margin;
// 上一次的位置
Vector3 lastPos;
// 脚本启用时调用
void OnEnable()
{
// 如果 UI 相机为空,则获取主相机
if (uiCamera == null) uiCamera = Camera.main;
// 如果仍然没有找到相机,输出警告并禁用脚本
if (uiCamera == null)
{
Debug.LogWarning("The uiCamera must not be null!");
this.enabled = false;
return;
}
// 在非编辑器模式下调整变换
#if !UNITY_EDITOR
redressTransform();
#endif
}
// 矩形区域
Rect mRect;
// 宽度和高度
float width, height;
// 中心点和垂直中心点
Vector2 center, vcenter;
// 向量
Vector3 v, sv;
// 在编辑器模式下的更新方法
#if UNITY_EDITOR
void Update()
{
// 如果 UI 相机为空,获取主相机
if (uiCamera == null)
{
uiCamera = Camera.main;
}
// 如果物体位置发生变化,更新边距偏移
if (Vector3.Distance(transform.position, lastPos) > 0.001f)
{
updateMarginOffset();
}
else
{
// 否则调整变换
redressTransform();
}
// 更新上一次的位置
lastPos = transform.position;
}
#endif
// 更新边距偏移
void updateMarginOffset()
{
if (uiCamera == null) return;
// 获取相机的像素矩形
mRect = uiCamera.pixelRect;
// 计算中心点
center = new Vector2((mRect.xMin + mRect.xMax) * 0.5f, (mRect.yMin + mRect.yMax) * 0.5f);
// 获取宽度和高度
width = mRect.width;
height = mRect.height;
// 将物体的世界坐标转换为屏幕坐标
v = uiCamera.WorldToScreenPoint(transform.position);
// 根据屏幕坐标确定象限
if (v.x >= center.x && v.y >= center.y)
{
vcenter = new Vector2(width, height);
quadrant = QuadrantLayout.Quadrant1;
}
else if (v.x >= center.x && v.y < center.y)
{
vcenter = new Vector2(width, 0);
quadrant = QuadrantLayout.Quadrant2;
}
else if (v.x < center.x && v.y < center.y)
{
vcenter = new Vector2(0, 0);
quadrant = QuadrantLayout.Quadrant3;
}
else if (v.x < center.x && v.y >= center.y)
{
vcenter = new Vector2(0, height);
quadrant = QuadrantLayout.Quadrant4;
}
// 计算边距
margin = new Vector2((v.x - vcenter.x), (v.y - vcenter.y));
}
// 调整变换
void redressTransform()
{
if (uiCamera == null) return;
// 获取相机的像素矩形
mRect = uiCamera.pixelRect;
// 获取宽度和高度
width = mRect.width;
height = mRect.height;
// 根据象限计算新的屏幕坐标
switch (quadrant)
{
case QuadrantLayout.Quadrant1:
sv = new Vector3(width + margin.x, height + margin.y, 0);
break;
case QuadrantLayout.Quadrant2:
sv = new Vector3(width + margin.x, margin.y, 0);
break;
case QuadrantLayout.Quadrant3:
sv = new Vector3(margin.x, margin.y, 0);
break;
case QuadrantLayout.Quadrant4:
sv = new Vector3(margin.x, height + margin.y, 0);
break;
}
// 获取物体在世界坐标中的 z 轴值
sv.z = uiCamera.WorldToScreenPoint(transform.position).z;
// 将屏幕坐标转换为世界坐标
sv = uiCamera.ScreenToWorldPoint(sv);
// 如果相机是正交相机,对坐标进行四舍五入
if (uiCamera.orthographic)
{
sv.x = Mathf.Round(sv.x);
sv.y = Mathf.Round(sv.y);
}
// 更新物体的位置
transform.position = sv;
}
}
使用说明
该方案根据象限来划分 UI 的位置,并在不同分辨率下自动调整。开发者无需设置任何属性,只需将 AutoLayout.cs 脚本附加到需要适配的物体上即可。
注意事项
代码中默认使用标签为 Main Camera 的相机。如果场景中有多个相机,需要确保 UI 相机被标记为 Main Camera,以保证适配功能正常工作。
以上就是 Unity 窗口适配的方案,希望对大家有所帮助。