Unity动态图集技术

.背景
首先,为什么需要动态图集?主要有两个原因:

游戏中的icon数量相当大,数量达到上千个。如果打成静态图集,需要好几张2048x2048的图集。运行时内存占用较大。同时,在这种情况下,由于icon会跨几个图集,在几个图集间穿插渲染有可能会提高drawcall。
若icon不打图集,每个icon就是一个单独的drawcall,会导致drawcall很高。
而动态图集,就是为了解决以上提到的问题。它的主要思路就是在运行时将需要使用的icon动态更新到一张共享的图集中去。由于同时渲染的icon数量往往远远小于实际icon的资源数量,因此通常一张1024或者2048大小的动态图集即可以满足大多数的游戏需求。该方法的好处在于,内存在可控范围,并且icon可以共享纹理从而省drawcall。

Unity动态图集技术

在 Unity 中,动态图集(Dynamic Atlas)技术是一种优化纹理资源管理和渲染性能的方法。动态图集通过将多个小纹理动态合并到一个大纹理中,减少了渲染过程中纹理切换的次数,从而提高了渲染效率。以下是关于 Unity 动态图集技术的详细介绍和实现方法。

动态图集的优势

  1. 减少纹理切换:在渲染过程中,频繁的纹理切换会导致性能下降。通过将多个小纹理合并到一个大纹理中,可以减少纹理切换的次数。
  2. 提高渲染效率:减少纹理切换和批处理次数,可以显著提高渲染效率,特别是在移动设备上。
  3. 简化资源管理:动态图集可以简化纹理资源的管理,使得纹理的加载和使用更加高效。

实现动态图集

在 Unity 中实现动态图集可以通过以下几种方法:

1. 使用 Unity 的 Sprite Atlas

Unity 提供了内置的 Sprite Atlas 工具,可以方便地创建和管理图集。以下是使用 Sprite Atlas 的步骤:

  1. 创建 Sprite Atlas

    • 在 Unity 编辑器中,右键点击项目窗口,选择 Create > 2D > Sprite Atlas 创建一个新的 Sprite Atlas。
  2. 添加精灵到图集

    • 选择创建的 Sprite Atlas,在 Inspector 窗口中,点击 Objects for Packing 下的 + 按钮,将需要合并的精灵(Sprite)拖动到列表中。
  3. 打包图集

    • 点击 Pack Preview 按钮,Unity 会自动将精灵合并到一个图集中。
  4. 使用图集中的精灵

    • 在代码或编辑器中使用图集中的精灵时,Unity 会自动从图集中提取相应的纹理。
2. 动态生成图集

如果需要在运行时动态生成图集,可以使用 Texture2DRect 类来实现。以下是一个简单的示例,展示了如何在运行时动态生成图集:

using UnityEngine;
using System.Collections.Generic;public class DynamicAtlas : MonoBehaviour
{public List<Texture2D> textures; // 要合并的纹理列表public int atlasWidth = 1024; // 图集宽度public int atlasHeight = 1024; // 图集高度private Texture2D atlasTexture;private List<Rect> uvRects;void Start(){GenerateAtlas();}void GenerateAtlas(){atlasTexture = new Texture2D(atlasWidth, atlasHeight);uvRects = new List<Rect>();for (int i = 0; i < textures.Count; i++){Texture2D texture = textures[i];Rect uvRect = new Rect(0, 0, texture.width, texture.height);uvRects.Add(uvRect);atlasTexture.SetPixels((int)uvRect.x, (int)uvRect.y, texture.width, texture.height, texture.GetPixels());}atlasTexture.Apply();}void OnGUI(){// 在屏幕上显示图集GUI.DrawTexture(new Rect(0, 0, atlasWidth, atlasHeight), atlasTexture);}
}
3. 使用第三方插件

除了 Unity 内置的工具和自定义实现外,还有一些第三方插件可以帮助你更方便地创建和管理动态图集。例如:

  • TexturePacker:一个流行的纹理打包工具,支持多种平台和格式,可以与 Unity 无缝集成。
  • Asset Store 插件:Unity Asset Store 上有许多插件提供了动态图集的功能,可以根据需要选择合适的插件。

动态图集的注意事项

  1. 纹理大小限制:在创建图集时,需要注意图集的大小限制。不同平台对纹理大小有不同的限制,通常建议图集的大小不超过 2048x2048 或 4096x4096。
  2. 纹理压缩:为了减少内存占用和提高加载速度,可以对图集进行纹理压缩。Unity 提供了多种纹理压缩格式,可以根据平台选择合适的压缩格式。
  3. 纹理边缘处理:在合并纹理时,需要注意纹理边缘的处理,避免出现纹理缝

动态图集pipeline

游戏应用逻辑根据资源路径向动态图集服务请求icon。
如果该icon已经在该图集中,直接返回给程序使用;否则进入第3步。
去硬盘上请求加载该icon。
加载完成以后将该icon载入内存。
动态图集服务会根据某种分块算法,在其剩余可用的区域里划分一块矩形区域,同时将第4步中的icon像素拷贝到该矩形区域。
将关联第5步中矩形区域的sprite返回给应用程序使用。
在该6个步骤中,第5步是核心步骤,因为分块算法的好坏和像素的拷贝直接决定该pipeline的性能瓶颈。

动态生成图集流程

动态生成图集(Dynamic Atlas)的流程涉及多个步骤,包括纹理的收集、图集的创建、纹理的合并以及图集的使用。以下是一个详细的流程和示例代码,展示如何在 Unity 中动态生成图集。

动态生成图集的流程

  1. 收集纹理:收集需要合并到图集中的所有纹理。
  2. 创建图集:创建一个空的图集纹理(Texture2D)。
  3. 合并纹理:将收集到的纹理逐个合并到图集中,并记录每个纹理在图集中的位置(UV 坐标)。
  4. 应用图集:将生成的图集应用到需要使用的对象上。

示例代码

以下是一个完整的示例代码,展示了如何在 Unity 中动态生成图集:

using UnityEngine;
using System.Collections.Generic;public class DynamicAtlasGenerator : MonoBehaviour
{public List<Texture2D> textures; // 要合并的纹理列表public int atlasWidth = 1024; // 图集宽度public int atlasHeight = 1024; // 图集高度public int padding = 2; // 纹理之间的间距private Texture2D atlasTexture;private List<Rect> uvRects;void Start(){GenerateAtlas();}void GenerateAtlas(){// 创建一个空的图集纹理atlasTexture = new Texture2D(atlasWidth, atlasHeight, TextureFormat.RGBA32, false);uvRects = new List<Rect>();// 初始化图集纹理为透明Color[] clearPixels = new Color[atlasWidth * atlasHeight];for (int i = 0; i < clearPixels.Length; i++){clearPixels[i] = Color.clear;}atlasTexture.SetPixels(clearPixels);// 当前图集的填充位置int currentX = padding;int currentY = padding;int maxRowHeight = 0;// 合并纹理到图集中foreach (Texture2D texture in textures){if (currentX + texture.width + padding > atlasWidth){// 换行currentX = padding;currentY += maxRowHeight + padding;maxRowHeight = 0;}if (currentY + texture.height + padding > atlasHeight){Debug.LogError("图集空间不足,无法容纳所有纹理");break;}// 复制纹理到图集atlasTexture.SetPixels(currentX, currentY, texture.width, texture.height, texture.GetPixels());// 记录纹理在图集中的位置Rect uvRect = new Rect((float)currentX / atlasWidth, (float)currentY / atlasHeight, (float)texture.width / atlasWidth, (float)texture.height / atlasHeight);uvRects.Add(uvRect);// 更新当前填充位置currentX += texture.width + padding;maxRowHeight = Mathf.Max(maxRowHeight, texture.height);}// 应用图集纹理atlasTexture.Apply();// 在屏幕上显示图集GameObject quad = GameObject.CreatePrimitive(PrimitiveType.Quad);quad.transform.localScale = new Vector3(10, 10, 1);quad.GetComponent<Renderer>().material.mainTexture = atlasTexture;}void OnGUI(){// 在屏幕上显示图集GUI.DrawTexture(new Rect(0, 0, atlasWidth, atlasHeight), atlasTexture);}
}

详细解释

  1. 收集纹理

    • public List<Texture2D> textures;:定义一个列表来存储需要合并的纹理。
  2. 创建图集

    • atlasTexture = new Texture2D(atlasWidth, atlasHeight, TextureFormat.RGBA32, false);:创建一个空的图集纹理。
    • 初始化图集纹理为透明:使用 SetPixels 方法将图集纹理初始化为透明。
  3. 合并纹理

    • 使用嵌套的循环遍历所有纹理,并将它们逐个复制到图集中。
    • 记录每个纹理在图集中的位置(UV 坐标),以便后续使用。
  4. 应用图集

    • atlasTexture.Apply();:调用 Apply 方法将所有的像素更改应用到图集纹理中。
    • 在屏幕上显示图集:创建一个四边形(Quad)并将图集纹理应用到其材质上,以便在场景中可视化图集。

使用图集中的纹理

在生成图集后,你可能需要在游戏中使用图集中的纹理。为了方便管理和使用这些纹理,可以创建一个简单的管理器类来存储纹理的 UV 坐标,并提供获取纹理 UV 坐标的方法。

以下是一个示例,展示如何使用生成的图集和 UV 坐标:

using UnityEngine;
using System.Collections.Generic;public class DynamicAtlasManager : MonoBehaviour
{public DynamicAtlasGenerator atlasGenerator; // 引用动态图集生成器private Dictionary<string, Rect> textureUVs; // 存储纹理名称和 UV 坐标的字典void Start(){textureUVs = new Dictionary<string, Rect>();// 假设纹理名称与列表中的索引对应for (int i = 0; i < atlasGenerator.textures.Count; i++){string textureName = atlasGenerator.textures[i].name;Rect uvRect = atlasGenerator.uvRects[i];textureUVs.Add(textureName, uvRect);}}public Rect GetTextureUV(string textureName){if (textureUVs.ContainsKey(textureName)){return textureUVs[textureName];}else{Debug.LogError("纹理名称不存在:" + textureName);return Rect.zero;}}
}

使用图集中的纹理示例

假设你有一个 2D 游戏,并且需要在精灵渲染器(SpriteRenderer)中使用图集中的纹理。以下是一个示例,展示如何使用 DynamicAtlasManager 获取纹理的 UV 坐标,并应用到精灵渲染器中:

using UnityEngine;public class SpriteFromAtlas : MonoBehaviour
{public DynamicAtlasManager atlasManager; // 引用动态图集管理器public string textureName; // 要使用的纹理名称void Start(){// 获取图集纹理Texture2D atlasTexture = atlasManager.atlasGenerator.atlasTexture;// 获取纹理的 UV 坐标Rect uvRect = atlasManager.GetTextureUV(textureName);// 创建一个新的精灵Sprite sprite = Sprite.Create(atlasTexture, new Rect(uvRect.x * atlasTexture.width, uvRect.y * atlasTexture.height, uvRect.width * atlasTexture.width, uvRect.height * atlasTexture.height), new Vector2(0.5f, 0.5f));// 应用精灵到精灵渲染器SpriteRenderer spriteRenderer = GetComponent<SpriteRenderer>();spriteRenderer.sprite = sprite;}
}

详细解释

  1. DynamicAtlasManager

    • textureUVs:一个字典,用于存储纹理名称和对应的 UV 坐标。
    • Start 方法:在开始时,将 DynamicAtlasGenerator 中的纹理名称和 UV 坐标存储到字典中。
    • GetTextureUV 方法:提供一个方法,根据纹理名称获取对应的 UV 坐标。
  2. SpriteFromAtlas

    • atlasManager:引用 DynamicAtlasManager,用于获取图集和 UV 坐标。
    • textureName:要使用的纹理名称。
    • Start 方法:在开始时,获取图集纹理和对应的 UV 坐标,创建一个新的精灵,并将其应用到精灵渲染器中。

总结

动态生成图集是一种有效的优化技术,可以减少纹理切换,提高渲染效率。通过收集纹理、创建图集、合并纹理和应用图集,可以在 Unity 中实现动态图集的生成和使用。通过管理器类,可以方便地管理和使用图集中的纹理,从而在游戏中实现高效的纹理管理和渲染。

动态生成图集性能问题

在 Unity 中动态生成图集虽然可以带来很多好处,但也可能引发一些性能问题。以下是一些常见的性能问题及其解决方案:

性能问题

  1. 图集生成时间

    • 动态生成图集需要时间,特别是当有大量纹理需要合并时,可能会导致明显的延迟。
    • 解决方案:尽量在非关键帧或加载屏幕期间生成图集,避免在游戏运行时频繁生成图集。
  2. 内存占用

    • 动态生成图集会占用额外的内存,特别是当图集尺寸较大时。
    • 解决方案:合理规划图集的尺寸,避免生成过大的图集。可以考虑将图集分割成多个较小的图集。
  3. 纹理上传到 GPU

    • 每次生成或更新图集后,需要将图集纹理上传到 GPU,这可能会导致性能瓶颈。
    • 解决方案:尽量减少图集的更新频率,避免频繁上传纹理到 GPU。
  4. 纹理拼接和边缘问题

    • 在合并纹理时,可能会出现纹理拼接不当或边缘渗色的问题。
    • 解决方案:在生成图集时添加适当的边距(padding),并使用纹理边缘扩展技术。

优化策略

  1. 预生成图集

    • 尽量在编辑器中预生成图集,而不是在运行时动态生成。可以使用 Unity 的 Sprite Packer 或第三方工具如 TexturePacker 来预生成图集。
  2. 异步生成图集

    • 如果必须在运行时生成图集,可以考虑使用异步方法来生成图集,避免阻塞主线程。
    • 示例代码:
      using UnityEngine;
      using System.Collections;
      using System.Collections.Generic;public class AsyncDynamicAtlasGenerator : MonoBehaviour
      {public List<Texture2D> textures;public int atlasWidth = 1024;public int atlasHeight = 1024;public int padding = 2;private Texture2D atlasTexture;private List<Rect> uvRects;void Start(){StartCoroutine(GenerateAtlasAsync());}IEnumerator GenerateAtlasAsync(){atlasTexture = new Texture2D(atlasWidth, atlasHeight, TextureFormat.RGBA32, false);uvRects = new List<Rect>();Color[] clearPixels = new Color[atlasWidth * atlasHeight];for (int i = 0; i < clearPixels.Length; i++){clearPixels[i] = Color.clear;}atlasTexture.SetPixels(clearPixels);int currentX = padding;int currentY = padding;int maxRowHeight = 0;foreach (Texture2D texture in textures){if (currentX + texture.width + padding > atlasWidth){currentX = padding;currentY += maxRowHeight + padding;maxRowHeight = 0;}if (currentY + texture.height + padding > atlasHeight){Debug.LogError("图集空间不足,无法容纳所有纹理");break;}atlasTexture.SetPixels(currentX, currentY, texture.width, texture.height, texture.GetPixels());Rect uvRect = new Rect((float)currentX / atlasWidth, (float)currentY / atlasHeight, (float)texture.width / atlasWidth, (float)texture.height / atlasHeight);uvRects.Add(uvRect);currentX += texture.width + padding;maxRowHeight = Mathf.Max(maxRowHeight, texture.height);yield return null; // 每次处理一个纹理后暂停,避免阻塞主线程}atlasTexture.Apply();}void OnGUI(){GUI.DrawTexture(new Rect(0, 0, atlasWidth, atlasHeight), atlasTexture);}
      }
      
  3. 分块生成图集

分块生成图集是一种将大图集分割成多个较小图集的方法,以减少单个图集的生成和更新时间。这种方法可以有效地管理内存和提高性能。

以下是一个示例代码,展示如何实现分块生成图集:

using UnityEngine;
using System.Collections.Generic;public class ChunkedAtlasGenerator : MonoBehaviour
{public List<Texture2D> textures; // 要合并的纹理列表public int chunkSize = 512; // 每个图集块的大小public int padding = 2; // 纹理之间的间距private List<Texture2D> atlasTextures; // 存储生成的图集块private List<List<Rect>> uvRectsList; // 存储每个图集块中纹理的 UV 坐标void Start(){GenerateChunkedAtlas();}void GenerateChunkedAtlas(){atlasTextures = new List<Texture2D>();uvRectsList = new List<List<Rect>>();int currentX = padding;int currentY = padding;int maxRowHeight = 0;Texture2D currentAtlas = CreateNewAtlas();List<Rect> currentUVRects = new List<Rect>();foreach (Texture2D texture in textures){if (currentX + texture.width + padding > chunkSize){// 换行currentX = padding;currentY += maxRowHeight + padding;maxRowHeight = 0;}if (currentY + texture.height + padding > chunkSize){// 当前图集块已满,创建新的图集块atlasTextures.Add(currentAtlas);uvRectsList.Add(currentUVRects);currentAtlas = CreateNewAtlas();currentUVRects = new List<Rect>();currentX = padding;currentY = padding;maxRowHeight = 0;}// 复制纹理到当前图集块currentAtlas.SetPixels(currentX, currentY, texture.width, texture.height, texture.GetPixels());// 记录纹理在当前图集块中的位置Rect uvRect = new Rect((float)currentX / chunkSize, (float)currentY / chunkSize, (float)texture.width / chunkSize, (float)texture.height / chunkSize);currentUVRects.Add(uvRect);// 更新当前填充位置currentX += texture.width + padding;maxRowHeight = Mathf.Max(maxRowHeight, texture.height);}// 添加最后一个图集块atlasTextures.Add(currentAtlas);uvRectsList.Add(currentUVRects);// 应用所有图集块foreach (var atlas in atlasTextures){atlas.Apply();}}Texture2D CreateNewAtlas(){Texture2D atlas = new Texture2D(chunkSize, chunkSize, TextureFormat.RGBA32, false);Color[] clearPixels = new Color[chunkSize * chunkSize];for (int i = 0; i < clearPixels.Length; i++){clearPixels[i] = Color.clear;}atlas.SetPixels(clearPixels);return atlas;}void OnGUI(){// 在屏幕上显示所有图集块for (int i = 0; i < atlasTextures.Count; i++){GUI.DrawTexture(new Rect(i * chunkSize, 0, chunkSize, chunkSize), atlasTextures[i]);}}
}

详细解释

  1. 创建新图集块

    • CreateNewAtlas 方法用于创建一个新的图集块,并初始化为透明。
  2. 生成分块图集

    • GenerateChunkedAtlas 方法遍历所有纹理,将它们逐个复制到当前图集块中。
    • 如果当前图集块已满,则创建一个新的图集块,并继续复制剩余的纹理。
  3. 记录 UV 坐标

    • 每个纹理在图集块中的位置(UV 坐标)被记录下来,以便后续使用。
  4. 应用图集块

    • 调用 Apply 方法将所有的像素更改应用到每个图集块中。
  5. 显示图集块

    • OnGUI 方法中,使用 GUI.DrawTexture 方法在屏幕上显示所有生成的图集块。

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

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

相关文章

[程序设计]—代理模式

[程序设计]—代理模式&#x1f473; 本文章记录学习于——52.面向切面&#xff1a;AOP-场景模拟_哔哩哔哩_bilibili 最近闲来无事&#xff0c;在学习Spring的源码&#xff1a; 后面慢慢更新源码系列blog&#xff0c;希望多多关注&#x1f64f;&#x1f64f; 目前已经总结的b…

我的128天创作之路:回顾与展望

大家好呀&#xff01;今天来和你们分享一下我的创作历程&#x1f601;。 一、机缘 最开始创作呢&#xff0c;是因为在学习 C 的 STL 时&#xff0c;像 string、list、vector 这些模板可把我折腾得够呛&#xff0c;但也让我学到了超多东西&#xff01;我就想&#xff0c;要是把我…

RAID储存技术

RAID独立磁盘冗余技术是一种把2个或者多个HDD或SSD合并为一个协调的存储单元或列阵&#xff0c;从而预防数据丢失的技术&#xff0c;其最早由加州大学伯克利分校的计算机科学家David Patterson、Garth Gibson和Randy Katz在1987年提出。他们的研究论文“关于RAID的论证”提出了…

Openstack持久存储-Swift,Cinder,Manila三者之间的区别

总结不易&#xff0c;给个三连吧&#xff01;&#xff01;&#xff01; 补充&#xff1a; 文件共享存储服务Manila 在OpenStack生态系统中&#xff0c;Cinder和Manila分别提供了两种不同类型的存储服务&#xff0c;类似于传统的SAN&#xff08;存储区域网络&#xff09;和NAS&…

软件测试预备知识④—NTFS权限管理、磁盘配额与文件共享

在软件测试的实际环境搭建与管理过程中&#xff0c;了解和掌握NTFS权限管理、磁盘配额以及文件共享等知识至关重要。这些功能不仅影响系统的安全性和稳定性&#xff0c;还对测试数据的存储、访问以及多用户协作测试有着深远的影响。 一、NTFS权限管理 1.1 NTFS简介 NTFS&am…

PyTorch深度学习CNN神经网络ResNet、DenseNet在CIFAR图像数据集分类应用与分析

全文链接&#xff1a;https://tecdat.cn/?p38782 在当今深度学习领域&#xff0c;卷积神经网络&#xff08;CNN&#xff09;架构不断发展与创新&#xff0c;诸多先进的架构被提出并广泛应用。像GoogleNet&#xff08;ILSVRC 2014获胜者&#xff09;、ResNet&#xff08;ILSVRC…

word论文排版常见问题汇总

word论文排版常见问题汇总 常用快捷键&#xff1a; Alt F9 正常模式与域代码模式切换 Ctrl F9 插入域代码 F9 刷新域代码显示&#xff0c;要注意选定后刷新才会有效果 word中在当前列表的基础上修改列表 在使用word时&#xff0c;我们会定义一个列表&#xff0c;并将其链接…

【Rust】数据类型

目录 思维导图 1. 数据类型概述 1.1 标量类型 1.1.1 整数类型 1.1.2 浮点数类型 1.1.3 布尔类型 1.1.4 字符类型 1.2 复合类型 1.2.1 元组类型 1.2.2 数组类型 2. 类型注解与类型推断 3. 整数溢出处理 4. 数字运算 5. 示例 思维导图 1. 数据类型概述 Rust是一种静…

Proteus-8086调试汇编格式的一点心得

这阵子开始做汇编的微机实验&#xff08;微机原理与接口技术题解及实验指导&#xff0c;吴宁版本13章&#xff09;&#xff0c;中间出了挺多问题&#xff0c;解决后记录下。 先上电路图 用子电路来仿真发现仿真的时候子电路这块根本没有高低电平输出&#xff0c;只好把子电路拿…

跨界融合:人工智能与区块链如何重新定义数据安全?

引言&#xff1a;数据安全的挑战与现状 在信息化驱动的数字化时代&#xff0c;数据已成为企业和个人最重要的资产之一。然而&#xff0c;随着网络技术的逐步优化和数据量的爆发式增长&#xff0c;数据安全问题也愈变突出。 数据安全现状&#xff1a;– 数据泄露驱动相关事件驱…

机器人碳钢去毛刺,用大扭去毛刺主轴可轻松去除

在碳钢精密加工的最后阶段&#xff0c;去除毛刺是确保产品质量的关键步骤。面对碳钢这种硬度较高的材料&#xff0c;采用大扭矩的SycoTec去毛刺主轴&#xff0c;成为了行业内的高效解决方案。SycoTec作为精密加工领域的领军品牌&#xff0c;其生产的高速电主轴以其卓越的性能&a…

大疆上云API连接遥控器和无人机

文章目录 1、部署大疆上云API关于如何连接我们自己部署的上云API2、开启无人机和遥控器并连接自己部署的上云API如果遥控器和无人机没有对频的情况下即只有遥控器没有无人机的情况下如果遥控器和无人机已经对频好了的情况下 4、订阅无人机或遥控器的主题信息4.1、订阅无人机实时…

[OPEN SQL] 限定选择行数

本次操作使用的数据库表为SCUSTOM&#xff0c;其字段内容如下所示 航班用户(SCUSTOM) 该数据库表中的部分值如下所示 指定查询多少行数据&#xff0c;我们可以使用语法UP TO n ROWS来实现对数据前n项的查询 语法格式 SELECT * FROM <dbtab> UP TO n ROWS 参数说明 db…

机器视觉3-线性分类器

机器视觉3-线性分类器 前言一、整体流程二、其他相关内容 图像的表示图像类型黑白图像灰度图像彩色图像 图像表示为向量一、基本概念二、表示方法三、优点四、局限性五、应用场景 线性分类器一、神经网络的层级结构形成非线性模型二、支撑向量机的高维映射形成非线性模型 线性分…

解决“无法定位程序输入点 av_buffer_create 于动态链接库 XXX\Obsidian.exe 上”问题

解决“无法定位程序输入点 av_buffer_create 于动态链接库 XXX\Obsidian.exe 上”问题 问题描述 本人在使用zotero中的zotero one&#xff08;青柠学术插件&#xff09;的时候&#xff0c;使用插件跳转obsidian中的对应笔记&#xff0c;出现上图情况。&#xff08;错误中提到的…

【数据结构高阶】B-树

目录 一、常见的搜索结构 二、B树 2.1 B树的概念 2.2 B树插入数据的分析 2.3 B树的性能分析 2.4 模拟实现B树 2.4.1 B树节点的定义 2.4.2 B树数据的查找 2.4.3 B树节点的数据插入 2.4.4 B树的遍历 2.4.5 模拟实现B树实现的完整代码 三、B树 3.1 B树的概念 3.2 B树…

《CPython Internals》阅读笔记:p97-p117

《CPython Internals》学习第 7 天&#xff0c;p97-p117 总结&#xff0c;总计 21 页。 一、技术总结 1.词法分析(lexical analysis) 根据《Compilers-Principles, Techniques, and Tools》(《编译原理》第2版)第 5 页&#xff1a;The first phase of a compiler is called …

2.两数相加--力扣

给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&#xff0c;这两个数都不会以 0 …

口碑很好的国产LDO芯片,有哪些?

在几乎任何一个电路设计中&#xff0c;都可能会使用LDO&#xff08;低压差线性稳压器&#xff09;这个器件。 虽然LDO不是什么高性能的IC&#xff0c;但LDO芯片市场竞争异常激烈。最近几年&#xff0c;诞生了越来越多的精品国产LDO&#xff0c;让人看得眼花缭乱。 业内人士曾经…

搜索引擎的设计与实现【源码+文档+部署讲解】

目 录 目 录 1 绪论 1.1 项目背景 1.2 国内外发展现状及分类 1.3 本论文组织结构介绍 2 相关技术介绍 2.1什么是搜索引擎 2.2 sqlserver数据库 2.3 Tomcat服务器 3 搜索引擎的基本原理 3.1搜索引擎的基本组成及其功能 3.2搜索引擎的详细工作流程 4 系统分析与…