UGUI Text/TextMeshPro字体组件

在这里插入图片描述

UGUI Text组件的不当使用及其性能瓶颈与优化

在Unity UGUI系统中,Text 组件(或其升级版 TextMeshPro)是显示文本信息的核心元素。然而,如果不当使用,它极易成为UI性能瓶颈的罪魁祸首,尤其是在预制体、属性设置和代码方法调用上。

1. UGUI Text组件的性能瓶颈分析

UGUI Text 组件的性能开销主要来源于以下几个方面:

  • 网格重建 (Mesh Regeneration):每次文本内容、字体大小、颜色、描边、阴影等属性发生变化时,Text 组件都需要重新生成用于渲染的网格数据。这个过程是CPU密集型的,尤其在文本内容复杂或数量众多时,会产生显著的性能峰值。
  • 批处理中断 (Batch Breaking)Text 组件通常使用字体图集(Font Atlas)进行渲染。如果场景中存在多个Text组件使用了不同的字体、不同的字体材质,或者它们的渲染顺序被其他UI元素打断,就会导致批处理中断,增加Draw Call数量,从而增加GPU负担。
  • 内存占用 (Memory Usage):字体资源(FontFont Atlas)本身会占用内存。如果使用了过多的字体种类或大尺寸的字体图集,会增加内存开销。此外,Text 组件在内部缓存网格数据也会占用内存。
2. UGUI Text组件的不当使用示例与优化方案

我们将从预制体、属性设置和代码方法三个维度来分析常见的不当使用及其优化方案。

2.1. 预制体(Prefab)中的不当使用

问题描述:
许多开发者习惯于在预制体中为每个需要显示文本的UI元素都创建一个独立的Text组件,即使这些文本的内容可能相似或为空。这种做法通常会导致:

  1. 过多的Text组件实例: 场景中存在大量即使不显示内容也占有资源的Text组件。
  2. 不必要的默认值设置: 预制体中设置了不必要的复杂文本样式(如描边、阴影),而这些样式在运行时可能并未使用。
  3. 字体资源冗余: 多个预制体引用了相同的字体,但可能没有进行有效的字体共享管理。

优化方案:

  • 按需实例化Text组件:

    • 示例: 假设有一个商品列表UI,每个商品项都是一个预制体。如果商品标题或描述不总是存在,可以考虑在预制体中不预设Text组件,而是在需要显示时动态实例化一个Text组件并添加到对应的父级下,或者使用一个预设的Text组件,但在不需要时禁用其GameObjectComponent
    • 性能提升: 减少初始化时的CPU开销和内存占用。禁用GameObjectComponent可以有效地停止其渲染和更新,从而减少性能消耗。
  • 简化预制体中的Text默认样式:

    • 示例: 在预制体中,将Text组件的默认样式设置为最简单的形式(例如,无描边、无阴影、最小字体大小)。仅在运行时根据需求动态应用更复杂的样式。
    • 性能提升: 降低文本网格重建的初始复杂性,减少不必要的计算。
  • 统一字体资源管理:

    • 示例: 建立一个集中的字体管理系统。所有UI文本都尽可能使用少量的通用字体,并通过TextMeshProFont Asset来管理字体变体(如粗体、斜体),而不是为每种样式都导入一个独立的字体文件。如果使用UGUI的Text,确保所有使用相同字体和大小的文本共享相同的Font资源。
    • 性能提升: 减少字体加载时的内存占用和Font Atlas的生成开销,有助于批处理,减少Draw Call。
2.2. 属性(Properties)设置中的不当使用

问题描述:
Text组件的Inspector面板中有许多属性,不当设置会导致性能问题:

  1. 频繁修改内容: 文本内容频繁变化会导致反复的网格重建。
  2. 复杂文本样式: 描边(Outline)、阴影(Shadow)等效果会增加网格的顶点数量,导致更复杂的网格重建和渲染。
  3. 字体大小与最佳匹配: 字体大小设置不当可能导致渲染模糊,或者为了清晰度而使用过大的字体资源。
  4. 自动换行与溢出模式: 复杂的换行和溢出模式(如“Best Fit”)需要额外的CPU计算来确定文本布局。

优化方案:

  • 最小化文本内容修改频率:

    • 示例: 对于频繁更新的文本(如计时器、分数),尽量避免每帧都更新text属性。可以通过缓存旧文本,只有当新文本与旧文本不同时才进行更新。
    • 代码示例:
      public TextMeshProUGUI scoreText; // 推荐使用TextMeshProUGUI
      private int currentScore = -1; // 初始化为一个不可能的值void UpdateScore(int newScore)
      {if (newScore != currentScore){currentScore = newScore;scoreText.text = "Score: " + currentScore.ToString();}
      }
      
    • 性能提升: 显著减少不必要的网格重建次数,降低CPU峰值。
  • 谨慎使用复杂文本样式:

    • 示例: 除非设计上明确要求,否则尽量避免使用OutlineShadow组件。如果必须使用,考虑是否可以通过美工预渲染到图片中,或者使用TextMeshProShader自带的描边/阴影功能,通常比额外的Outline/Shadow组件更高效,因为它们集成在单个网格和材质中,减少了额外的Draw Call。
    • 性能提升: 减少网格顶点数量,降低CPU网格生成和GPU渲染的开销。
  • 优化字体大小与使用TextMeshPro

    • 示例: 尽量使用预设的字体大小,避免使用Best Fit模式。如果文本大小需要动态调整,考虑使用TextMeshProTextMeshPro通过距离场字体渲染(SDF)技术,可以在不同字体大小下保持清晰度,而无需生成大量的字体图集,从而减少内存占用和网格重建的开销。对于UGUI Text,确保字体大小与UI元素的实际显示尺寸匹配,避免过大的字体图集。
    • 性能提升: TextMeshPro显著减少字体资源大小和网格重建频率,提高文本渲染效率。UGUI Text在字体图集管理上不如TextMeshPro灵活,因此更需要注意字体大小和图集生成。
  • 合理设置自动换行与溢出模式:

    • 示例: 如果文本内容是固定的或不经常变化,尽量设置为“Wrap”模式,而不是“Best Fit”。“Best Fit”会进行额外的计算来找到最合适的字体大小,这在每次文本内容或容器大小变化时都会触发。对于不需要自动换行的文本,取消勾选“Word Wrap”。
    • 性能提升: 减少CPU在文本布局计算上的开销。
2.3. 代码方法(Code Methods)中的不当使用

问题描述:
在脚本中与Text组件交互时,一些常见的编程习惯会导致性能问题:

  1. 频繁的GetComponent<Text>()调用:Update或循环中重复获取组件引用。
  2. 不必要的字符串操作: 频繁地拼接字符串,尤其是在每帧或高频率的事件中。
  3. 直接修改导致频繁重建: 直接修改text属性,而不是通过适当的逻辑判断避免不必要的更新。

优化方案:

  • 缓存组件引用:

    • 示例:AwakeStart方法中获取一次Text组件的引用,并在后续方法中直接使用缓存的引用。
    • 代码示例:
      public TextMeshProUGUI myTextComponent; // 在Inspector中赋值// 或者在代码中获取一次
      void Awake()
      {if (myTextComponent == null){myTextComponent = GetComponent<TextMeshProUGUI>();}
      }void Update()
      {// 直接使用缓存的引用// myTextComponent.text = "Hello World";
      }
      
    • 性能提升: 避免了GetComponent带来的性能开销,尤其是在Update中,能显著减少CPU时间。
  • 优化字符串操作:

    • 示例: 对于需要频繁更新的数字文本,使用ToString()而不是字符串拼接。如果需要复杂的字符串格式化,考虑使用StringBuilder来避免产生过多的临时字符串对象,从而减少GC(Garbage Collection)压力。
    • 代码示例(避免GC):
      using System.Text;
      public TextMeshProUGUI dynamicText;
      private StringBuilder sb = new StringBuilder();void UpdateStatus(string playerName, int level)
      {sb.Clear();sb.Append("Player: ").Append(playerName).Append(", Level: ").Append(level);dynamicText.text = sb.ToString();
      }
      
    • 性能提升: 减少内存分配和GC开销,保持帧率稳定。
  • 逻辑判断避免不必要的更新:

    • 示例: 只有当文本内容确实发生变化时才更新text属性。这与前面“最小化文本内容修改频率”的原则一致。
    • 代码示例:
      public TextMeshProUGUI statusText;
      private string cachedStatus = "";void SetStatus(string newStatus)
      {if (newStatus != cachedStatus){cachedStatus = newStatus;statusText.text = cachedStatus;}
      }
      
    • 性能提升: 避免不必要的网格重建,减少CPU开销。
总结

Text组件在Unity UI中无处不在,其性能优化至关重要。通过对预制体中Text组件的实例化策略、Inspector中属性的谨慎设置以及代码中对Text组件的正确操作,我们可以有效避免常见的性能陷阱。在实际项目中,强烈推荐优先使用TextMeshPro而非传统的UGUI Text组件,因为它在渲染效率、内存占用和功能性上都具有显著优势,能够更轻松地实现高性能的文本显示。

请记住,性能优化是一个持续的过程,需要结合Unity Profiler进行数据驱动的分析和迭代。


TextMeshPro 资源管理深度解析

TextMeshPro的核心优势之一在于其基于距离场(Signed Distance Field, SDF)的字体渲染技术,这使得字体在任意大小下都能保持清晰,并且支持更丰富的文本样式。而其资源管理方式,特别是Font Asset的使用,是实现这些优势的关键。

1. TextMeshPro Font Asset 生命周期

Font Asset是TMP最重要的资源类型,它包含了字体元数据、SDF纹理图集(Font Atlas)以及字符映射信息。理解其生命周期对于性能和内存管理至关重要。

  • 创建阶段:

    • Font Asset通常由Unity编辑器通过菜单 Window > TextMeshPro > Font Asset Creator 从TrueType (.ttf) 或 OpenType (.otf) 字体文件创建。
    • 创建过程中,你可以定义字体大小、字符集(ASCII、常用汉字等)、渲染模式(SDF、Bitmap)、以及是否包含额外纹理(如Fallbacks)。
    • 生成的.asset文件就是Font Asset
  • 加载阶段:

    • 当场景中存在使用该Font AssetTextMeshProUGUITextMeshPro组件时,或者当代码中通过Resources.Load()Addressables.LoadAssetAsync()等方式显式加载时,Font Asset及其关联的SDF纹理图集会被加载到内存中。
    • Font Asset本身是一个小型数据文件,但其SDF纹理图集(通常是PNG或TGA格式)可能较大,其加载会占用GPU和CPU内存。
  • 使用阶段:

    • 一旦Font Asset加载到内存,所有引用它的TMP组件都可以共享其SDF纹理。这意味着即使有成千上万个TMP组件,只要它们使用相同的Font Asset,就只需要一份字体纹理数据。
    • 当TMP组件需要渲染文本时,它会查找Font Asset中的字符信息,并从SDF纹理中提取对应的SDF数据来生成字符网格。
  • 卸载阶段:

    • Font Asset的卸载通常遵循Unity的资源卸载机制。
    • 如果Font Asset没有被任何场景中的对象引用,且没有被脚本代码强引用(例如,存储在一个静态变量中),在场景切换或手动调用Resources.UnloadUnusedAssets()时,它有机会被卸载。
    • 如果使用Addressables,可以通过Addressables.Release()Addressables.ReleaseInstance()来显式卸载。
    • 重要提示: Font Asset通常包含SDF纹理,如果纹理没有被释放,即使Font Asset对象本身被销毁,其占用的GPU内存可能仍然存在。确保所有引用被释放,并调用Resources.UnloadUnusedAssets()(如果不是Addressables)是必要的。
2. TextMeshPro 与 Addressables 打包

将TMP Font Asset与Unity Addressables系统结合使用是大型项目资源管理和性能优化的最佳实践。它允许你按需加载字体,减少启动时内存占用,并支持热更新。

  • 为何使用Addressables?

    • 按需加载: 字体只在需要时加载,而不是在游戏启动时全部加载。
    • 内存优化: 避免长时间驻留内存的不常用字体。
    • 减少包体大小: 将字体作为可下载内容,核心包体更小。
    • 热更新: 可以在不更新客户端的情况下更新字体资源。
    • 依赖管理: Addressables会自动处理Font Asset与其SDF纹理的依赖关系。
  • 设置步骤:

    1. 启用Addressables: Window > Asset Management > Addressables > Groups,然后点击 Create Addressables Settings
    2. 创建Font Asset: 正常通过Font Asset Creator创建你的Font Asset
    3. 标记为Addressable:
      • 在Project视图中选中你的Font Asset
      • 在Inspector中,勾选Addressable复选框。
      • 或者直接将Font Asset拖入Addressables Groups窗口中,它会自动被标记。
    4. 构建Addressables: Window > Asset Management > Addressables > Groups,然后点击Build > Build New Playable Content
    5. 运行时加载:
      • 在代码中通过Addressables.LoadAssetAsync<TMP_FontAsset>(address)来异步加载Font Asset
      • 加载完成后,将其赋值给TextMeshProUGUITextMeshPro组件的fontSharedMaterial属性或直接设置font属性(对于TMP组件,设置font属性会自动处理材质)。
  • 代码示例(异步加载和使用):

    using UnityEngine;
    using TMPro;
    using UnityEngine.AddressableAssets;
    using UnityEngine.ResourceManagement.AsyncOperations;public class DynamicFontLoader : MonoBehaviour
    {public TextMeshProUGUI targetText;public AssetReferenceT<TMP_FontAsset> fontAssetReference; // 在Inspector中拖拽设置private TMP_FontAsset _loadedFontAsset;private AsyncOperationHandle<TMP_FontAsset> _loadHandle;void Start(){if (fontAssetReference != null){LoadFontAsset();}}async void LoadFontAsset(){_loadHandle = fontAssetReference.LoadAssetAsync<TMP_FontAsset>();await _loadHandle.Task; // 等待加载完成if (_loadHandle.Status == AsyncOperationStatus.Succeeded){_loadedFontAsset = _loadHandle.Result;if (targetText != null){targetText.font = _loadedFontAsset; // 自动处理材质targetText.text = "字体已动态加载!";}}else{Debug.LogError($"Failed to load font asset: {_loadHandle.OperationException}");}}void OnDestroy(){// 务必释放Addressables资源if (_loadHandle.IsValid() && _loadHandle.IsDone){Addressables.Release(_loadHandle);_loadedFontAsset = null;}}
    }
    
3. 动态字体(Dynamic Fonts)

TMP支持两种字体渲染模式:SDF(Signed Distance Field)和Bitmap。虽然所有TMP字体都通过Font Asset管理,但我们可以让Font Asset支持"动态"添加字符,这对于处理用户输入或多语言支持尤其有用。

  • 核心概念:

    • Font Asset Creator中,当你选择Render ModeDistance Field时,你通常会预设一个字符集(如ASCII、Extended ASCII、Japanese等)。
    • 当运行时,如果TMP组件需要显示一个Font Asset中没有的字符,它会尝试从原始的TrueTypeOpenType字体文件中渲染这个字符,并将其动态添加到Font Asset的SDF纹理图集中。
    • 限制: 这种动态添加字符的行为会触发SDF纹理的重建和上传到GPU,这会带来一定的CPU和GPU开销,尤其是在首次遇到大量新字符时。
  • 使用场景:

    • 用户输入: 当用户可以在输入框中输入任何字符时。
    • 多语言支持: 当游戏需要支持多种语言,且无法在编译时确定所有需要显示的字符时。
    • 少量不常用字符: 对于一些偶尔出现、不值得预先打包到Font Asset中的字符。
  • 性能考量与优化:

    • 预打包常用字符: 尽可能在Font Asset Creator中包含所有常用字符集(例如,如果支持中文,预打包常用汉字)。这样可以最大程度减少运行时的动态添加。

    • Fallbacks机制: TMP支持Font Asset Fallbacks。你可以为主字体设置多个备用字体,当主字体不包含某个字符时,TMP会自动尝试从备用字体中查找。这比动态生成更高效,因为备用字体也是预先生成好的Font Asset

    • 示例: 你可以有一个主要的英文SDF字体,然后设置一个包含常用中文字符的SDF字体作为Fallback

    • 设置Fallback:

      1. 在Project视图中选中你的主Font Asset
      2. 在Inspector中找到Font Asset组件,展开Fallback Font Assets列表。
      3. 将你希望作为备用的Font Asset拖入此列表中。
4. TextMeshPro 字体完整制作流程

制作一个高质量且性能优化的TMP字体是一个系统性的过程。

步骤 1: 准备原始字体文件 (.ttf/.otf)

  • 选择合适的字体: 确保字体文件是高质量的,且有合法的授权。
  • 清理字体文件(可选): 有时字体文件可能包含不必要的元数据或字符,可以使用字体编辑工具(如FontForge)进行清理。

步骤 2: 使用 Font Asset Creator 创建 Font Asset

  1. 打开 Font Asset Creator: 在Unity编辑器中,导航到 Window > TextMeshPro > Font Asset Creator

  2. 设置 Source Font File: 将你的 .ttf.otf 字体文件拖拽到此字段,或点击选择。

  3. 设置 Atlas Resolution:

    • 这是生成SDF纹理图集的大小。
    • 重要: 越大越清晰,但占用内存也越多。
    • 推荐: 512x512 或 1024x1024 通常足够用于大部分UI文本。对于需要超大显示的标题,可以考虑2048x2048。
    • 性能考量: 过大的图集不仅占用内存,也会增加加载时间。
  4. 设置 Padding:

    • 字符之间的间距,用于避免渲染时字符边缘出现“漏光”现象。
    • 推荐: 5-9 像素。
  5. 设置 Packing Mode:

    • Fast:更快的生成速度,可能稍微多占用空间。
    • Optimum:更优化的空间利用,生成时间稍长。
    • 推荐: 大多数情况下使用Fast即可。
  6. 设置 Rendering Mode:

    • Distance Field (SDF):推荐,允许字体在不同大小下保持清晰,且支持高质量的描边、阴影等效果。
    • Bitmap:传统的像素渲染,不推荐用于高质量UI,只在特定像素艺术风格中可能使用。
  7. 设置 Character Set:

    • 选择你希望包含的字符集。
    • ASCII 英文数字常用符号。
    • Extended ASCII 包含更多特殊字符。
    • Custom Characters 手动输入或从文本文件导入特定字符列表。
    • Characters from File 从包含所有所需字符的文本文件中导入。
    • Characters from Font 从原始字体文件中扫描所有可用字符(这可能导致巨大的图集和内存占用,慎用)。
    • 优化: 尽可能只包含实际需要的字符,避免打包不必要的字符。对于中文等CJK语言,通常需要使用Characters from FileCharacters from Font,但要做好字符集筛选,否则图集会非常大。
  8. 设置 Atlas Population Mode:

    • Static:默认模式,所有字符在创建时打包到图集。
    • Dynamic:允许运行时动态添加字符(如前面所述)。
    • 推荐: 大多数固定文本使用Static。如果需要支持用户输入或多语言,且无法预知所有字符,可考虑Dynamic,但要配合Fallbacks或预打包常用字符进行优化。
  9. Generate Font Atlas: 点击此按钮生成SDF纹理图集。

  10. Save TextMeshPro Font Asset: 生成成功后,点击此按钮保存.asset文件。这将保存Font Asset及其生成的SDF纹理。

步骤 3: 调整 Font Asset Inspector 属性

保存后,在Project视图中选中新创建的Font Asset,可以在Inspector中进行进一步调整:

  • Material Preset: 可以创建材质预设来统一管理字体渲染效果(颜色、描边、阴影等)。
  • Font Feature Table: 调整字体特性,如字距调整(Kerning Pair)。
  • Fallback Font Assets: 配置备用字体,用于处理主字体中缺失的字符。
  • Character Spacing Options: 调整字符间距。

步骤 4: 在 TMP 组件中使用 Font Asset

  1. TextMeshProUGUI组件添加到你的UI元素上。
  2. 在Inspector中,将你创建的Font Asset拖拽到Font Asset字段。
  3. 根据需要调整MaterialText属性。
总结

TextMeshPro的资源管理核心在于Font Asset,它将字体数据、纹理和渲染信息封装在一起。通过合理地创建Font Asset(控制分辨率、字符集),结合Addressables进行按需加载和卸载,以及利用Fallbacks机制,可以实现高性能、低内存占用且灵活的文本渲染。对于动态字体需求,理解其内部工作原理并采取预打包、Fallbacks等优化手段是关键,避免过度依赖运行时的动态生成,从而保障UI的流畅性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/84054.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…

【个人笔记】数据库原理(西电)

写在前面&#xff1a;文中提到的页面指向&#xff08;如“p45”&#xff09;&#xff0c;除特别说明&#xff0c;都是指对应ppt上的页面&#xff0c;非同款ppt的友友可忽略 第一章 ER图和关系分解见课本p69 ER图是常用的 概念模型 方形&#xff1a;实体圆形&#xff1a;属性…

SDC命令详解:使用set_propagated_clock命令进行约束

相关阅读 SDC命令详解https://blog.csdn.net/weixin_45791458/category_12931432.html?spm1001.2014.3001.5482 目录 指定端口列表/集合 简单使用 注意事项 传播时钟是在进行了时钟树综合后&#xff0c;使用set_propagated_clock命令可以将一个理想时钟转换为传播时钟&#x…

关于华为仓颉编程语言

文章目录 一、基本概况二、技术特点1. 多范式编程2. 原生智能化3. 高性能与安全4. 全场景兼容 三、编译器与开发工具四、语言相似性对比五、行业应用实例总结 最近经常看到这个东西&#xff0c;于是搜了一下&#xff0c;整理了一些内容&#xff0c;水一篇&#xff0c;以后慢慢研…

【STM32F1标准库】理论——定时器中的输出比较

目录 一、定时器的输出比较介绍&#xff08;Output Compare&#xff09; 1.整体简介 2.输出比较单元具体功能框图 3.以PWM模式1举例 二、杂谈 1.CCR的全名 2.PWM简介 3.舵机简介 4.直流电机及驱动模块TB6612简介 一、定时器的输出比较介绍&#xff08;Output Compare…

前端开发面试题总结-HTML篇

文章目录 HTML面试高频问答一、HTML 的 src 和 href 属性有什么区别?二、什么是 HTML 语义化?三、HTML的 script 标签中 defer 和 async 有什么区别?四、HTML5 相比于 HTML有哪些更新?五、HTML行内元素有哪些? 块级元素有哪些? 空(void)元素有哪些?六、iframe有哪些优点…

Scrapy爬虫教程(新手)

1. Scrapy的核心组成 引擎&#xff08;engine&#xff09;&#xff1a;scrapy的核心&#xff0c;所有模块的衔接&#xff0c;数据流程梳理。 调度器&#xff08;scheduler&#xff09;&#xff1a;本质可以看成一个集合和队列&#xff0c;里面存放着一堆即将要发送的请求&#…

Transformer-BiLSTM、Transformer、CNN-BiLSTM、BiLSTM、CNN五模型时序预测

Transformer-BiLSTM、Transformer、CNN-BiLSTM、BiLSTM、CNN五模型时序预测 目录 Transformer-BiLSTM、Transformer、CNN-BiLSTM、BiLSTM、CNN五模型时序预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Transformer-BiLSTM、Transformer、CNN-BiLSTM、BiLSTM、CNN五…

历史数据分析——唐山港

个股简介 公司简介: 唐山港口投资有限公司、北京京泰投资管理中心、河北利丰燕山投资管理中心、国富投资公司、唐山市建设投资公司、河北省建设投资公司、国投交通实业公司7家发起人共同发起设立。 经营分析: 港口经营一般项目:港口货物装卸搬运活动;普通货物仓储服务(不含…

云端回声消除:让超低端硬件能玩实时打断

传统认知里“优质交互 高性能硬件”的等式正在被打破&#xff1f; 超低端开发板也能实现高配置硬件才有的实时打断语音交互&#xff1f; 网易云信推出的云端回声消除技术不仅解决了硬件配置对交互体验的限制&#xff0c;更以系统性解决方案重构了嵌入式设备的实时对话体验。 困…

堆排序的详细解读

一.堆的基本概念 1.什么是堆 堆是一种特殊的完全二叉树&#xff0c;满足一下性质&#xff1a; 最大堆&#xff1a;每个节点的值都大于或等于其子节点的值&#xff08;堆顶元素最大&#xff09;最小堆&#xff1a;每个节点的值都小于或等于其子节点的值&#xff08;堆顶元素最小…

hmdp知识点

1. 前置知识 1.1 MyBatisPlus的基本使用 1.1.1 引入依赖 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.3</version> </dependency> 1.1.2 建立实体类和数…

分享5个免费5个在线工具网站:Docsmall、UIED Tool在线工具箱、草料二维码、图片在线压缩、表情符号

01. Docsmall 它是一个免费的在线图片与PDF处理工具&#xff0c;功能主要包含Ai图片处理工具&#xff0c;图片压缩工具&#xff0c;图片PDF格式转换工具等&#xff0c;如下图&#xff0c;我认为比较实用的是自动抠图、图片变高清、图片压缩和PDF压缩。 https://docsmall.com/…

打通印染车间“神经末梢”:DeviceNet转Ethernet/IP连接机器人的高效方案

在印染行业自动化升级中&#xff0c;设备联网需求迫切。老旧印染设备多采用Devicenet协议&#xff0c;而新型工业机器人普遍支持Ethernet/IP协议&#xff0c;协议不兼容导致数据交互困难&#xff0c;设备协同效率低、生产监控滞后&#xff0c;成了行业数字化转型的阻碍。本文将…

RSA加密算法:非对称密码学的基石

一、RSA算法概述 RSA&#xff08;Rivest-Shamir-Adleman&#xff09;是1977年由Ron Rivest、Adi Shamir和Leonard Adleman提出的非对称加密算法&#xff0c;它基于大数分解的数学难题&#xff0c;是当今应用最广泛的公钥密码系统。RSA的核心思想是使用一对密钥&#xff08;公钥…

杭州瑞盟 MS35774/MS35774A 低噪声256细分微步进电机驱动,用于空调风门电机驱动,香薰电机驱动

杭州瑞盟 MS35774/MS35774A 低噪声256细分微步进电机驱动&#xff0c;用于空调风门电机驱动&#xff0c;香薰电机驱动 简述 MS35774/MS35774A 是一款高精度、低噪声的两相步进 电机驱动芯片&#xff0c;芯片内置功率 MOSFET &#xff0c;长时间工作的平均电 流可以达到 1…

驶向智能未来:车载 MCP 服务与边缘计算驱动的驾驶数据交互新体验

引言 在人工智能技术与车载算力持续突破的驱动下&#xff0c;现代车辆的数字化进程正加速推进。车联网系统将突破传统云端架构的局限&#xff0c;依托边缘计算与 AI 融合技术&#xff0c;实现人车交互体验的范式重构‌。通过构建基于多源异构数据的自动化分析框架&#xff0c;…

Python数据可视化科技图表绘制系列教程(三)

目录 单一柱状图 分组柱状图 堆积柱状图 百分比柱状图 均值柱状图 不等宽柱状图 有序柱状图 条形图 发散条形图 在条上添加标签的发散条形图 基础棒棒糖图1 基础棒棒糖图2 【声明】&#xff1a;未经版权人书面许可&#xff0c;任何单位或个人不得以任何形式复制、发…

JavaScript 数组与流程控制:从基础操作到实战应用

在 JavaScript 编程的世界里&#xff0c;数组是一种极为重要的数据结构&#xff0c;它就像是一个有序的 “收纳盒”&#xff0c;能够将多个值整齐地存储起来。而流程控制语句则像是 “指挥官”&#xff0c;能够按照特定的逻辑对数组进行遍历和操作。接下来&#xff0c;就让我们…

十(1). 强制类型转换

继第十部分C强制类型转换的四种方式&#xff0c;再进行强化巩固一下知识点 static_cast 最常用的&#xff0c;在指针之间做转换 const_cast 去除常量属性 dynamic_cast 用在基类和派生类之间的转换 reinterpret_cast 在任意类型之间进行转 10.1 static_cast 常见的使用场景&am…