unity 像素ui的适配问题

1.导入设置问题

像素ui的导入需要调整ppu值,一般是2的倍数

filter mode 改成point模式

format改成自动或者 rgba32 bit模式

压缩模式改为高质量或者none

2.ui缩放问题导致像素对不上

ui的缩放需要成整数的倍数的缩放,canvas模式改成scale content screen size 模式进行适配

调整好模板比例后再进行拼ui, ppu也要和图片的导入的ppu进行同步

3.效果图和ui拼后的不一样

美术要规范,要在指定的大小范围内进行拼效果,不能随性,图的大小规格要适配参考比例大小

图片导出的时候要仔细,不然图片和效果图之间有出入

4.ui的适配问题

需要调整锚点来控制缩放,根据屏幕的宽高比进行适配

5.脚本适配代码

挂载到canvas下即可,选择适合你的方式

using UnityEngine;

using UnityEngine.UI;

/// <summary>

/// 像素完美 Canvas 自动配置

/// 挂载到 Canvas 上,自动处理不同分辨率适配

/// </summary>

RequireComponent(typeof(Canvas))

RequireComponent(typeof(CanvasScaler))

public class PixelPerfectCanvasSetup : MonoBehaviour

{

Header("基准设置")

Tooltip("基准分辨率(美术资源设计的目标分辨率)")

public Vector2Int baseResolution = new Vector2Int(1920, 1080);

Tooltip("像素每单位(与 Sprite PPU 保持一致)")

public float pixelsPerUnit = 32f;

Header("缩放策略")

Tooltip("缩放模式")

public ScalingMode scalingMode = ScalingMode.IntegerScaling;

Tooltip("屏幕匹配权重(0=宽度优先,1=高度优先,0.5=平衡)")

Range(0f, 1f)

public float matchWidthOrHeight = 0.5f;

Header("像素对齐")

Tooltip("启用像素对齐(避免模糊)")

public bool enablePixelSnapping = true;

Tooltip("运行时动态调整")

public bool updateAtRuntime = true;

private Canvas canvas;

private CanvasScaler canvasScaler;

private int lastScreenWidth;

private int lastScreenHeight;

public enum ScalingMode

{

/// <summary>整数倍缩放(最清晰,但可能有黑边)</summary>

IntegerScaling,

/// <summary>自适应缩放(填满屏幕,可能略微模糊)</summary>

AdaptiveScaling,

/// <summary>固定像素尺寸(不缩放,可能裁剪)</summary>

ConstantPixelSize

}

void Awake()

{

canvas = GetComponent<Canvas>();

canvasScaler = GetComponent<CanvasScaler>();

ApplyPixelPerfectSettings();

}

void Start()

{

lastScreenWidth = Screen.width;

lastScreenHeight = Screen.height;

}

void LateUpdate()

{

if (!updateAtRuntime) return;

// 检测分辨率变化

if (Screen.width != lastScreenWidth || Screen.height != lastScreenHeight)

{

ApplyPixelPerfectSettings();

lastScreenWidth = Screen.width;

lastScreenHeight = Screen.height;

}

}

/// <summary>

/// 应用像素完美设置

/// </summary>

public void ApplyPixelPerfectSettings()

{

canvas.pixelPerfect = true;

switch (scalingMode)

{

case ScalingMode.IntegerScaling:

ApplyIntegerScaling();

break;

case ScalingMode.AdaptiveScaling:

ApplyAdaptiveScaling();

break;

case ScalingMode.ConstantPixelSize:

ApplyConstantPixelSize();

break;

}

Debug.Log($"PixelPerfect 分辨率: {Screen.width}x{Screen.height}, " +

$"缩放: {canvasScaler.scaleFactor:F2}x, " +

$"模式: {scalingMode}");

}

/// <summary>

/// 整数倍缩放(推荐用于像素艺术)

/// 优点:完美清晰

/// 缺点:可能有黑边

/// </summary>

private void ApplyIntegerScaling()

{

canvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;

canvasScaler.referenceResolution = baseResolution;

canvasScaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;

canvasScaler.matchWidthOrHeight = matchWidthOrHeight;

canvasScaler.referencePixelsPerUnit = pixelsPerUnit;

// 计算整数倍缩放

int scaleX = Mathf.Max(1, Screen.width / baseResolution.x);

int scaleY = Mathf.Max(1, Screen.height / baseResolution.y);

int scale = Mathf.Min(scaleX, scaleY);

// 调整参考分辨率以实现整数倍缩放,确保为偶数避免像素完美渲染警告

int adjustedWidth = Screen.width / scale;

int adjustedHeight = Screen.height / scale;

// 强制转换为偶数(向下取整到最近的偶数)

adjustedWidth = MakeEven(adjustedWidth);

adjustedHeight = MakeEven(adjustedHeight);

Vector2 adjustedResolution = new Vector2(adjustedWidth, adjustedHeight);

canvasScaler.referenceResolution = adjustedResolution;

}

/// <summary>

/// 确保数值为偶数(向下取整到最近的偶数)

/// </summary>

private int MakeEven(int value)

{

return (value / 2) * 2;

}

/// <summary>

/// 自适应缩放(推荐用于混合风格)

/// 优点:填满屏幕

/// 缺点:可能轻微模糊

/// </summary>

private void ApplyAdaptiveScaling()

{

canvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;

canvasScaler.referenceResolution = baseResolution;

canvasScaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;

canvasScaler.matchWidthOrHeight = matchWidthOrHeight;

canvasScaler.referencePixelsPerUnit = pixelsPerUnit;

}

/// <summary>

/// 固定像素尺寸(不推荐,仅特殊情况)

/// </summary>

private void ApplyConstantPixelSize()

{

canvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ConstantPixelSize;

canvasScaler.scaleFactor = 1f;

canvasScaler.referencePixelsPerUnit = pixelsPerUnit;

}

/// <summary>

/// 获取当前像素缩放比例

/// </summary>

public float GetCurrentScale()

{

return canvasScaler.scaleFactor;

}

/// <summary>

/// 获取整数倍缩放级别

/// </summary>

public int GetIntegerScaleLevel()

{

int scaleX = Mathf.Max(1, Screen.width / baseResolution.x);

int scaleY = Mathf.Max(1, Screen.height / baseResolution.y);

return Mathf.Min(scaleX, scaleY);

}

void OnValidate()

{

// 编辑器中实时预览

if (Application.isPlaying && canvas != null && canvasScaler != null)

{

ApplyPixelPerfectSettings();

}

}

}

相关推荐
johnny2332 小时前
UI新革命?GenUI、WanDB-OpenUI、thesysdev-OpenUI、A2UI、AG-UI、MCP-UI
ui
天天进步201511 小时前
UI-TARS 源码解析 #10:parse_action 源码解析:如何用 AST 安全解析模型生成的函数调用?
安全·ui
FuckPatience20 小时前
Telerik UI for WPF 值不能为null。参数名:key
ui·wpf
breeze jiang21 小时前
从原生事件到 React 组件化:用状态驱动模型加载进度 UI
前端·react.js·ui
JaneConan2 天前
鸿蒙 ArkUI 深水区:@Watch 和 @Observed,状态变了「自动跑」+ 嵌套对象「深层重绘」
开发语言·后端·ui·harmonyos
施棠海2 天前
Pixel2XML实战:10分钟从设计稿做出一个能拨号的Android拨号盘页面(附完整业务代码)
android·java·ui
施棠海2 天前
设计稿一键变成可运行的Android页面:Pixel2XML全流程UI开发框架实战(附完整源码)
android·ui·架构
Helen_cai2 天前
OpenHarmony 通用状态加载、空页面、错误兜底组件封装(全局业务通用 UI 组件 API23)
开发语言·ui·华为·php·harmonyos
YM52e2 天前
鸿蒙 Flutter BoxDecoration装饰:打造精美UI效果
学习·flutter·ui·华为·harmonyos·鸿蒙
qq_463408422 天前
# 基于 HarmonyOS ArkTS 声明式 UI 构建智能音乐播放器:深色主题圆盘轮播、五 Tab 导航隔离、瀑布流收藏与悬浮迷你播放条实现深度解析
ui·华为·harmonyos