1.导入设置问题

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

filter mode 改成point模式

format改成自动或者 rgba32 bit模式

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

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

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

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

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

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

图片导出的时候要仔细,不然图片和效果图之间有出入,最好不要有小数的缩放

在拼ui的时候要选择好分辨率进行拼,比如1920*1080,这个是对应的效果图

4.ui像素的适配问题

需要调整锚点来控制缩放,根据屏幕的宽高比进行适配,动态调整 canvas scaler中的math值,ugui会自行适配,ui的位置最好得是整数值,有小数的时候,像素点有可能对不上

需要拉伸的ui就不建议点这个适配宽高的,有的图就会差那么点

不需要拉伸的,就点这个

use sprite mesh 这个也看具体情况,有时候图他会超出image一定范围,勾选了这个的话会限制在image的范围内

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();
        }
    }
}

更多推荐