一、目标平台
- 目前在Window上没有问题,其他平台没试过
二、需求
- 我们游戏的背包中经常需要拖拽一个道具到某个地方,并完成一些功能,比如:镶嵌、强化、修理,放至其他背包中等等操作。
- 功能实现了,但是遇到了适配的问题,我们是以1920x1080为参考去做的UI,也就是当前画布的分辨率设置的就是1920x1080,如果屏幕分辨率大于或小于这个参考分辨率就会在拖拽时出现问题:拖拽时鼠标的位置会和UI元素的位置发生偏移。
三、画布缩放器(Canvas Scaler)
- 画布缩放器组件用于控制画布中 UI 元素的整体缩放和像素密度。此缩放会影响画布下的所有内容,包括字体大小和图像边框。
- 缩放模式(UI Scale Mode) 分为三种,我使用的是第二种(Scale With Screen Size),所以这里只介绍第二种。
四、Scale With Screen Size
- 屏幕分辨率越大,UI元素也会越大,反之会越来越小。
- 属性Reference Resolution:用于画布缩放的参考分辨率,我们在制作UI时就以这个参考分辨率去做即可。
- 属性Screen Match Mode:当屏幕分辨率和参考分辨率不一致时,对画布缩放的方式
五、Screen Match Mode
- Match Width or Height:以宽度、高度或二者的某种平均值作为参考来缩放画布区域
- Expand:水平或垂直扩展画布区域,使画布不会小于参考
- Shrink:水平或垂直裁剪画布区域,使画布不会大于参考
六、Math Width or Height
- 值为0,则代表以宽度作为参考来缩放画布,即Canvas的宽度不会变,一直为参考分辨率的宽度(1920);
当屏幕分辨率与参考分辨率不一致时,会使用参考分辨率的宽度来参与计算,并得出画布的高度;
计算过程:float baseW = 1920f; // 参考分辨率的宽 flaot baseH = 1080f; // 参考分辨率的高 float wRate = baseW / Screen.width; float hRate = baseH / Screen.height; float rate = wRate / hRate; float canvasH = baseH * rate;
- 值为1,则代表以高度作为参考来缩放画布,即Canvas的高度不会变,一直为参考分辨率的高度(1080);
当屏幕分辨率与参考分辨率不一致时,会使用参考分辨率的高度来参与计算,并得出画布的宽度;
计算过程:float baseW = 1920f; // 参考分辨率的宽 flaot baseH = 1080f; // 参考分辨率的高 float wRate = baseW / Screen.width; float hRate = baseH / Screen.height; float rate = hRate / wRate; float canvasW = baseW * rate;
七、实现思路
- 有了上面计算好的基础内容,我们便可以使拖拽适配与各分辨率了
- UI Scale Mode 设置为:Scale With Screen Size
- Canvas的参考分辨率设置为:1920 x 1080
- Screen Match Mode 设置为:可以根据自身情况选择
- 如果Mode设置为MathWidthOrHeight则这里只实现Match为0或1的情况
- 要拖拽的UI元素上挂在实现了IDragHandler接口的Mono
- 下面代码实现了四种模式,请根据自身情况选择:
public void OnDrag(PointerEventData eventData) { if (!eventData.dragging) return; Vector2 delta = eventData.delta; // 适配分辨率,拖拽 float baseW = 1920f; // 参考分辨率的宽 float baseH = 1080f; // 参考分辨率的高 float wRate = baseW / Screen.width; float hRate = baseH / Screen.height; float finalRate; // 模式:Match Width 0 float matchWidthRate = wRate / hRate; float canvasH = baseH * matchWidthRate; //finalRate = canvasH / Screen.height; // 模式:Match Height 1 float matchHeightRate = hRate / wRate; float canvasW = baseW * matchHeightRate; //finalRate = canvasW / Screen.width; // 模式:Expand(扩张) // 匹配宽度(宽度保持在基础宽度,高度一直在变) //if (canvasW < baseW) //{ // finalRate = canvasH / Screen.height; // canvasW = baseW; //} 匹配高度(高度保持在基础高度,宽度一直在变) //else //{ // finalRate = canvasW / Screen.width; // canvasH = baseH; //} // 模式:Shrink(收缩) // 匹配宽度(宽度保持在基础宽度,高度一直在变) if (canvasW > baseW) { finalRate = canvasH / Screen.height; canvasW = baseW; } // 匹配高度(高度保持在基础高度,宽度一直在变) else { finalRate = canvasW / Screen.width; canvasH = baseH; } delta *= finalRate; m_Rect.anchoredPosition += delta; Debug.Log($"Screen:[{Screen.width},{Screen.height}]---canvas:[{canvasW},{canvasH}]"); }
如果你也有这样的需求,并且帮到了你,请点赞收藏起来吧!!