当前位置: 首页 > news >正文

Unity 手机屏幕适配

手机屏幕适配主要分为

1、手机安全交互区域适配(例如需要处理刘海屏)

2、界面内部UI元素相对位置适配

准备工作

1、对Canvas设置

(1)设置Render Mode为Screen Space-Camera,并赋值相机的引用

(2)设置UI Scale Mode 为 Scale With Screen Size,并设置项目分辨率

2、安装设备模拟器

(Device Simulator)

该插件可以帮助我们模拟游戏在手机上运行时的适配效果

Unity 2021之前的版本都是预览包,需要手动下载,

打开package Manager,进行设置

勾选启用预览包

搜索下载 模拟器

在Game窗口切换使用

点击Safe Area 显示设备安全区域

切换设备型号

安全区域适配

需要处理三类屏幕适配情况:

1、只需要适配上端区域

型号

Apple iPad Air 2

Google Pixel 5

Huawei P40 Pro

Motorola Moto G7 Power

OnePlus 6T

Samsung Galaxy Note10

Samsung Galaxy Note10+ 5G

Samsung Galaxy Note20 Ultra 5G

Samsung Galaxy S10 5G

Samsung Galaxy S10+

Samsung Galaxy S10e

Samsung Galaxy Z Fold2 5G_1

Samsung Galaxy Z Fold2 5G_2

Xiaomi Mi A3

Xiaomi Redmi 6 Pro

Xiaomi Redmi Note7

2、只需要适配下端区域

型号

Apple iPad Pro 11

Apple iPad Pro 12.9(2018)

2、上端和下端区域都适配

型号

Apple iPad Air (4th generation)

Apple iPhone 11

Apple iPhone 12

Apple iPhone 12 Pro

Apple iPhone 12 Pro Max

Apple iPhone 12 Mini

Apple iPhone X

Apple iPhone XR

Apple iPhone XS

Apple iPhone XS Max

创建MatchManager

using UnityEngine;
using UnityEngine.UI;

public enum MatchDimension
{
    None = 1,
    Width = 2,
    Height = 3
}

public class MatchManager : MonoBehaviour
{
    private CanvasScaler _canvasScaler;

    private RectTransform _canvasRect;

    const float DesignW = 1080;
    const float DesignH = 1920;
    
    private float DesignRatio;   //标准参考比率

    private float screenWidth;   //手机屏幕宽度
    private float screenHeight;  //手机屏幕高度
    
    private float safeAreaX;
    private float safeAreaY;       
    private float safeAreaWidth;   //手机安全区域宽度
    private float safeAreaHeight;  //手机安全区域高度
    
    private float CanvasRectWidth => _canvasRect == null ? DesignW : _canvasRect.rect.width;

    private float CanvasRectHeight => _canvasRect == null ? DesignH : _canvasRect.rect.height;
    
    void Start()
    {
        _canvasScaler = GetComponent<CanvasScaler>();
        _canvasRect = GetComponent<RectTransform>();
        if (_canvasScaler == null)
        {
            var canvasObj = GameObject.Find("/GameRoot/UIRoot");
            if(canvasObj!=null)
            {
                _canvasScaler = canvasObj.GetComponent(typeof(CanvasScaler))as CanvasScaler;
                _canvasRect = canvasObj.GetComponent<RectTransform>();
            }
        }

        if (_canvasScaler.matchWidthOrHeight == 0)
        {
            if (CanvasRectHeight <= DesignH)
            {
                //需要改为高度适配
                ChangeReference((int)MatchDimension.Height);
            }
        }
        else if (NumberTool.IsSameFloat(_canvasScaler.matchWidthOrHeight,1))
        {
            if (CanvasRectWidth <= DesignH)
            {
                //需要改为宽度适配
                ChangeReference((int)MatchDimension.Width);
            }
        }
        InitConfigData();
    }
    
    /// <summary>
    /// 初始化适配时需要的配置数据
    /// </summary>
    private void InitConfigData()
    {
        DesignRatio = DesignW / DesignH;
        var factRatio = CanvasRectHeight / Screen.height;
        safeAreaX = Screen.safeArea.x*factRatio;
        safeAreaY = Screen.safeArea.y*factRatio;
        safeAreaWidth = Screen.safeArea.width*factRatio;
        safeAreaHeight = Screen.safeArea.height*factRatio;
        screenWidth = CanvasRectWidth;
        screenHeight = CanvasRectHeight;
    }

    /// <summary>
    /// 切换参考维度
    /// </summary>
    public void ChangeReference(int md)
    {
        if (_canvasScaler == null)
        {
            return;
        }

        if (md == (int)MatchDimension.Width)
        {
            _canvasScaler.matchWidthOrHeight = 0;
        }
        else if (md == (int)MatchDimension.Height)
        {
            _canvasScaler.matchWidthOrHeight = 1;
        }
    }
    
    /// <summary>
    /// 限制UI元素在安全区域
    /// </summary>
    public void LimitSafeArea(RectTransform rect)
    {
        var offset = screenHeight - safeAreaHeight;
        if (safeAreaY == 0)
        {
            if (offset > 0)
            {
                //仅需适配屏幕top
                rect.offsetMax = new Vector2(rect.offsetMax.x, rect.offsetMax.y-offset);
            }
        }
        else
        {
            if ((int)offset == (int)safeAreaY)
            {
                //仅需适配屏幕bottom
                rect.offsetMin = new Vector2(rect.offsetMin.x, rect.offsetMin.y + offset);
            }
            else if ((int)offset > (int)safeAreaY)
            {
                //需适配屏幕top和bottom
                var bottomOffset = safeAreaY;
                var topOffset = screenHeight - safeAreaHeight - bottomOffset;

                rect.offsetMin = new Vector2(rect.offsetMin.x, rect.offsetMin.y + bottomOffset);
                rect.offsetMax = new Vector2(rect.offsetMax.x, rect.offsetMax.y -topOffset);
            }
        }
    }
}

将该脚本附加到Canvas节点上

创建MatchUIContent

using UnityEngine;

public class MatchUIContent : MonoBehaviour
{
    void Start()
    {
        var rect = GetComponent<RectTransform>();
        MatchManager.Instance.LimitSafeArea(rect);
    }
}

在界面预制体中创建一个单独的节点main,在该节点下进行界面拼接

把MatchUIContent 脚本附加在Main节点上

UI界面适配

主要是处理界面内UI节点间的对齐关系

主要有16种对齐方式

1、点对齐:长宽不变,位置移动,跟随对齐点适配

2、中心点对齐:长宽不变,位置不移动

3、拉伸对齐:长或宽会变,中心位置不移动,跟随界面拉伸

提示:拼接好界面后,多通过手机模拟器界面查看测试,如果遇到界面不适配的情况,就去进行调整。

相关文章:

  • 简站主题:简洁、实用、SEO友好、安全性高和后期易于维护的wordpress主题
  • 记一次 Git Fetch 后切换分支为空的情况
  • oppo,汤臣倍健,康冠科技25届春招内推
  • 二、几何体BufferGeometry顶点笔记
  • 【MySQL高级】17 - MySQL中常用工具
  • 3.hadoop3.3.6 HA集群搭建
  • SpringBoot源码解析(十):应用上下文AnnotationConfigServletWebServerApplicationContext构造方法
  • 深度学习-1.简介
  • 深入探索 DeepSeek 在数据分析与可视化中的应用
  • qemu启动aarch64 linux+ buildroot + 应用程序
  • MAVSDK - Custom Mavlink处理
  • mybatis-mp正式改名为xbatis!!!
  • deepseek+ollama+anythingllm在本地搭建个人知识库
  • ollama server启动服务后如何停止
  • HTML之JavaScript DOM(document)编程处理事件
  • Java编程语言:从基础到高级应用的全面探索
  • 火语言RPA--Excel打开文档
  • OpenHarmony 系统性能优化——默认关闭全局动画
  • DIEN:深度兴趣演化网络
  • AI领域技术架构
  • 站酷设计官方网站/郑州网站
  • 婚介网站建设的策划/营销策划公司名称
  • 网站做关键词库的作用/谷歌网站收录提交入口
  • wordpress登陆界面打开慢/seo 重庆
  • 长清做网站公司/注册网站查询
  • 海南房产网站开发/百度博客收录提交入口