自由学习记录(130)

add selection to next find match,

作用是定位之后的整体光标移动,比如重点是加光标了,其实还是没什么用的感觉

alt f在当前文件找层次已经可以

  • Ctrl + Click(鼠标点击)

    默认行为是 Go to Definition(跳转到定义)

    效果:直接打开定义所在文件并跳转过去。

    等价快捷键:F12

  • Alt + F12

    这是 Peek Definition(查看定义)

    效果:在当前编辑器里弹出一个小窗口显示定义,不离开当前文件。

  • 更多有效源码 是好事
  • 更多缓存、生成物、编译产物 通常不是好事

真正有价值被扫描的,通常是:

  • Source
  • 你自己会改的 Plugins 源码
  • Config
  • 少量必要脚本
  • 某些你确实会读的引擎接口头文件

而"全扫"带来的坏处常常大于收益的目录是:

  • Intermediate
  • Binaries
  • DerivedDataCache
  • Saved
  • .vs

原因是这些目录虽然也属于项目,但它们大多是:

  • 自动生成
  • 变化频繁
  • 数量巨大
  • 搜索噪音很多
  • 对理解业务逻辑帮助很小

clangd 是 LLVM/Clang 项目的 C++ 语言服务器(Language Server)

简单理解:它是一个负责 代码补全、跳转定义、诊断、重构等 IDE 功能的后台服务,VSCode 只是前端 UI。

所以结构其实是:

VSCode

→ 语言服务器插件

→ 语言服务器(clangd / cpptools)

VSCode 本身并不真正理解 C++,它只是调用这些语言服务器。

微软的 C/C++ (cpptools) 更像 通用型解决方案

  • 为 VSCode 提供 IntelliSense

  • 适配 Windows / Linux / Mac

  • 不依赖特定编译系统

  • 自动扫描 workspace 推测 include path

所以它的策略通常是:

扫描 workspace

→ 尝试推断编译环境

→ 构建索引

优点是:

开箱即用

小项目体验很好

缺点是:

大型工程容易爆炸

UE、Chromium、LLVM 这种项目动辄:

  • 十几万文件

  • 巨型 include tree

  • 大量宏

cpptools 就会开始:

overflow-visible! 复制代码

Enumerating files
Indexing
Building IntelliSense database

于是你刚才看到:

overflow-visible! 复制代码

289k files
185k C++ files

clangd 的思路完全不同

clangd 不猜工程结构,而是 直接使用真实编译信息

它依赖一个文件:

overflow-visible! 复制代码

compile_commands.json

这个文件来自编译系统(UBT / CMake / Bazel 等),里面记录:

  • 每个 cpp 的编译命令

  • include path

  • 宏定义

  • 编译选项

例如:

overflow-visible! 复制代码

clang++ -IEngine/... -DUE_BUILD ...

clangd 只会解析:

overflow-visible! 复制代码

真正参与编译的文件

而不会扫描整个 workspace。

所以流程变成:

compile_commands.json

→ clangd

→ 精确语义分析

这也是为什么它在大型项目上更稳定。

为什么 UE 不默认生成?

因为 UE 默认开发工具是:

  • Visual Studio

  • Rider

  • Xcode

这些 IDE 不需要 compile_commands.json

而 clangd / clang-based IDE 才需要。

所以 UE 只在你请求时生成。

workspace

  • myOne/ (项目)

  • UE5/ (引擎源码目录)

这是典型的 源码版 UE + 项目同级目录 的布局。

UE5/** 整体排除,会出现几个实际问题:

  1. F12 无法跳转到引擎代码

  2. IntelliSense / clangd 类型解析变弱

  3. UE 宏、模板、容器(TArray、TObjectPtr 等)提示变差

  4. 编译错误定位只停留在项目层

对于 C++ UE 开发,这通常是不可接受的。

Refresh VS Code Project 是 Unreal Editor 用来 重新生成 VS Code 的工程配置文件 的操作。本质上是调用 UnrealBuildTool (UBT) 重新生成 IDE 支持文件,使 VS Code 能正确解析 UE 项目结构。

它主要做的事情可以分成四类。

第一类:重新生成 VS Code 工作区配置。

UE 会重新生成 .vscode 目录下的文件,例如:

  • tasks.json

  • launch.json

  • c_cpp_properties.json

  • compileCommands.json(如果启用)

这在 VS Code 里叫多根工作区。

每个根目录都可以各自有自己的 .vscode。

你可以粗暴理解成:

  • myOne/.vscode 管你项目
  • UE5/.vscode 管引擎源码

这也解释了为什么你会看到两个。

如果你主要只是写项目代码,通常更应该关心的是:

  • myOne/.vscode

而 UE5/.vscode 只有在你也打算直接读/改引擎源码时才更重要。

另外,这也意味着一件事:

  • 你现在的工作区负担会比"只开 myOne"更重
  • 因为你把整个 UE5 根目录也一起放进 workspace 了

是因为 "Unity 不开源" 本身直接导致只显示一个 .vscode,而是因为你通常不会把 Unity 引擎源码目录也作为一个工作区根一起打开。

所以常见情况是:

  • Unity 项目里,你只打开项目目录
  • 于是通常只看到项目自己的 .vscode

而 UE 这边你现在是:

  • 同时打开了 myOne
  • 又打开了 UE5

所以会看到两个 .vscode:

  • 项目的
  • 引擎目录的

Unity 和 UE 的差别更准确地说是:

  • Unity 引擎源码通常不是你本地项目工作区的一部分
  • UE 引擎源码/引擎目录经常会被直接放进工作区一起看

Unity 里你日常更常面对的是:

  • Assets
  • Packages
  • Unity 提供的托管 API

你确实也会看文档、反编译、看 package 源码,但一般不会像 UE 那样长期把"整个引擎源码根目录"放在工作区里一起工作。

所以差别本质上是:

  • UE:看引擎源码是高频行为
  • Unity:看项目代码和包代码更常见,看整个引擎源码不是日常默认动作

换句话说:

  • UE 开发常常是"项目 + 引擎一起读"
  • Unity 开发更多是"项目为主,必要时查包或 API"
overflow-visible! 复制代码

myOne.sln
.vscode
myOne.code-workspace

全部是 IDE层文件

你截图里特殊的目录

截图里还有:

overflow-visible! 复制代码

Backup
UE5
UpgradeLog.htm

这通常来自:

UE 项目升级

例如:

overflow-visible! 复制代码

UE4 → UE5

UE 会自动生成:

overflow-visible! 复制代码

Backup/
UpgradeLog.htm

用于记录迁移日志。

VSCode Workspace 为什么叫 workspace

workspace 只是:

overflow-visible! 复制代码

IDE 的工作区

例如可以同时打开:

overflow-visible! 复制代码

Engine
Project
Plugin

例如很多 UE 开发者会这样:

overflow-visible! 复制代码

workspace
├─ UnrealEngine
└─ MyGame

这样可以:

  • 跳转 Engine 源码

  • Debug 引擎

  • 修改插件

但实际上:

overflow-visible! 复制代码

UE 编译完全不依赖 workspace

UE 项目最小结构

理论最小 UE C++ 项目:

overflow-visible! 复制代码

MyGame
├─ Source
│ └─ MyGame
│ ├─ MyGame.Build.cs
│ ├─ MyGame.cpp
│ └─ MyGame.h
├─ Config
├─ Content
└─ MyGame.uproject

其他:

overflow-visible! 复制代码

Binaries
Intermediate
Saved

全部可以删。

UE 会自动重新生成。

我先看一下当前 myOne.code-workspace 怎么组织这两个根,这样能准确判断:把 UE5 加到哪一级的排除里,会不会把引擎源码整个隐藏掉。

Ran Get-Content .vscode/settings.json for 1s

Ran Get-Content myOne.code-workspace for 1s

Worked for 28s

不会。

按你现在这个结构,myOne/.vscode/settings.json 里的排除规则只作用在 myOne 这个根上,不会把另一个根 UE5 整个隐藏掉。

原因是你这个工作区是双根的,在 myOne.code-workspace 里明确分成了:

  • myOne,路径是 .
  • UE5,路径是 E:\UE_5.5

而你现在编辑的 settings.json 是 myOne 这个根自己的文件夹设置。它能排除的是:

  • myOne 根下面的目录
  • 比如 Binaries、Intermediate 这种

它不能跨去把同级的另一个工作区根 UE5 整个弄消失。

你可以这样记:

  • myOne/.vscode/settings.json

    只管 myOne

  • UE5/.vscode/settings.json

    只管 UE5

  • myOne.code-workspace 里的 "settings"

    才是整个多根工作区都可能一起吃到的设置

所以如果你在当前这个 settings.json 里加类似 UE5 的排除:

  • 大概率没效果
  • 因为 UE5 不是 myOne 目录下的子目录

真要让引擎源码在资源管理器里整体消失,通常要么:

  • myOne.code-workspace 的工作区级 settings 里配排除
  • 要么直接把 UE5 这个根从 workspace 里移除

所以结论是:

  • 加在你当前这个 myOne/.vscode/settings.json 里,不会把引擎源码整个隐藏掉
  • 真正能影响两个根的是 .code-workspace

一个实用经验是:
引擎源码只保留两类目录
Engine/Source
Engine/Shaders

其余绝大部分目录对 C++ 索引价值很低。

件事本质上属于 VSCode 的文件系统与工作区机制 ,与是否使用 clangd 并没有直接关系。

settings.json 里的这些配置:

overflow-visible! 复制代码

files.exclude
search.exclude
files.watcherExclude

都是 VSCode Core 层在处理,而不是语言服务器。

它们作用在三个地方:

  1. Explorer 文件树

  2. 全局搜索 (ripgrep)

  3. 文件系统 watcher

也就是说,即使没有安装任何 C++ 插件,这些规则依然生效。

需要区分一点:语言服务器是否会读取这些规则

不同 LSP 的行为不同。

clangd

clangd 不依赖 VSCode 的 exclude

它主要根据:

overflow-visible! 复制代码

compile_commands.json
compile_flags.txt

来确定索引哪些 translation unit。

即使 VSCode Explorer 隐藏了某些目录:

overflow-visible! 复制代码

Engine/Binaries
Engine/Intermediate

如果这些文件被 compile_commands.json 引用,clangd 仍然可能解析。

不过 UE 的 compile_commands.json 通常只包含:

overflow-visible! 复制代码

Engine/Source
Project/Source
Plugins/Source

因此缓存目录本身不会进入 clangd 的 TU 集。

UE 编辑器启动后打开哪个关卡由 Editor Startup Map 控制,而不是自动记住上次关闭时的关卡。因此如果不配置,它通常会回到模板项目的默认关卡。

要让 UE 启动时直接进入你想继续工作的关卡,需要修改编辑器启动地图。

步骤:

  1. 打开
    Edit → Project Settings

  2. 找到
    Project → Maps & Modes

  3. 里面有两个关键设置:

Editor Startup Map

Game Default Map

含义:

Editor Startup Map

控制 UE编辑器启动时加载的关卡

Game Default Map

控制 游戏运行(Play/Package)时加载的关卡

  1. Editor Startup Map 改成你常用的关卡,例如:
overflow-visible! 复制代码

/Game/Maps/MainLevel

保存后,下次打开项目就会直接进入这个关卡。


如果你的需求是 "始终打开上一次关闭时的关卡"(而不是固定某个关卡),UE 默认其实有一个相关选项。

打开:

overflow-visible! 复制代码

Edit
→ Editor Preferences
→ Loading & Saving

找到:

overflow-visible! 复制代码

Load Level at Startup

设置为:

overflow-visible! 复制代码

Last Opened

可选值通常是:

overflow-visible! 复制代码

Project Default
Last Opened

设置为 Last Opened 后:

UE 会在退出时记录当前关卡,下次启动时直接恢复。

iagara (拼写:N-i-a-g-a-r-a),不是 Nigara。UE5 中 Cascade 基本已经进入维护状态,所有新特效体系都围绕 Niagara。

可编程粒子与视觉效果系统(data-driven VFX framework)

类似于:

  • Unity:VFX Graph + Particle System

  • Houdini:POP / VEX 系统

  • Frostbite:Data-driven particle graph

性能优化基本围绕三个层面:Simulation 成本、Renderer 成本、以及数据交互成本 。如果从引擎层或图形工程角度看,优化重点通常不是单一节点,而是 粒子数量、更新频率、以及 GPU/CPU 执行路径选择。下面按实际工程中最影响性能的几个方向说明。Niagara 最大的性能差异来自是否使用 GPU simulation。

CPU Niagara:

  • 粒子更新在游戏线程 / worker thread

  • 每个粒子逐个执行模块

  • 通常粒子数量建议 < 1000--3000

GPU Niagara:

  • 通过 compute shader 执行

  • 可支持 10万级粒子

典型优化策略是:

小规模、需要 Gameplay 交互的特效:

overflow-visible! 复制代码

CPU Niagara

大规模视觉粒子:

overflow-visible! 复制代码

GPU Niagara

例如:

烟雾

火焰

魔法粒子

雪雨

几乎都应该 GPU 化。

UE 的 profiler 中可以看到:

overflow-visible! 复制代码

stat Niagara

如果看到:

overflow-visible! 复制代码

Niagara CPU Sim

占用明显,就说明 emitter 应该迁移到 GPU。

Niagara 确实能做出"很多粒子同时受力、碰撞、反弹、流动"这类效果,但这通常不是你脑子里那种 Chaos 刚体物理 ,而更接近 大规模并行粒子模拟 。Niagara 的核心是 System / Emitter / Module 这套粒子框架,并且支持 GPU 仿真与碰撞模块,所以它能在一个系统里同时驱动大量粒子。它大多数时候跑的不是"刚体世界",而是简化粒子动力学

Niagara 粒子通常只维护很少的状态:位置、速度、年龄、颜色、尺寸、朝向,再加上少量自定义属性。每帧做的常见更新也只是积分这类简单步骤:
v += a * dtx += v * dt,外加阻尼、噪声、碰撞修正。

这和 Chaos 里每个物体都要做碰撞体管理、接触约束求解、睡眠、岛屿分解、刚体堆叠稳定化,不是一个量级。也就是说,很多 Niagara "看起来像物理"的效果,本质上只是廉价得多的粒子更新。Niagara 的碰撞能力也是通过专门的 Collision 模块提供,而不是默认进入完整刚体求解。GPU Ray Tracing Collisions 这类面向 GPU simulation 的能力;同时 Niagara 还支持 Simulation Stages / GPU 计算路径来做更复杂的迭代更新。

烟雾如果从严格 CFD 看,应该是:

  • 速度场

  • 压力场

  • 密度场

  • 温度场

这是欧拉网格表示。

但在实时 VFX 里,通常没必要完全求解。

只要让很多粒子:

  • 从某区域生成

  • 向上漂

  • 带噪声扰动

  • 生命周期渐隐

人眼就会把它识别成烟。

烟雾的感知阈值很低,粒子近似已经够骗过视觉系统。

Emitter 正好就是这个模型:

  • Spawn Rate

  • Burst

  • Shape Location

  • Initial Velocity

所以一个烟源只要配:

  • 圆环 / 球 / 盒 的发射区域

  • 合适 spawn rate

  • 初速度

  • 噪声力

烟雾主要靠统计外观,不靠单个粒子精度

做火花时,你会很在意每个粒子的轨迹。

这些 UI 词看起来像"普通界面标签",但其实每一个都直接对应 粒子模拟管线中的一个阶段(simulation stage) 。Niagara 的 UI 本质上是在可视化一条 粒子生命周期执行图 Emitter → Spawn → Update → Render一个 Niagara System 可以包含多个 emitter。System OverviewEmitter Settings / Emitter PropertiesEmitter 是 粒子生成器实例

一个 emitter 负责:

  • 产生粒子

  • 管理粒子生命周期

  • 更新粒子状态

Emitter Spawnemitter 创建时执行一次。

因为"重力"这件事对粒子来说,在数值上极其便宜,而且天然适合 GPU 的数据并行模型

真正贵的通常不是"重力",而是:

  • 碰撞

  • 邻域搜索

  • 约束求解

  • 排序

  • 透明混合 overdraw

  • CPU↔GPU 同步

  • BVH / 网格 / 场采样

对单个粒子,一帧的最基础更新通常只有这几步:

overflow-visible! 复制代码

Plain text
v = v + g * dt
x = x + v * dt

如果更完整一点,再带上阻尼:

overflow-visible! 复制代码

Plain text
v = (v + g * dt) * damping
x = x + v * dt

这本质上只是少量向量加法和乘法。

假设位置、速度都是 float3,每个粒子一帧也就十几个到几十个 FLOPs 量级,远远算不上复杂物理。

把同一个 kernel 扔给海量线程执行即可。

非常理想的 SIMT 负载:

  1. 指令一致

  2. 内存访问模式规则

  3. 很少分支

  4. 粒子之间独立

  5. 容易批量调度

这五条几乎就是"GPU 友好型算法"的教科书条件。

体地说,为什么"重力"特别便宜?

第一,它是常量场

重力通常就是:

overflow-visible! 复制代码

Plain text
g = (0, 0, -980)

所有粒子读的是同一个常量,甚至可以直接放在常量缓存里。

所以每个线程根本不需要复杂查询,也不需要随机访存。

十万独立粒子受重力 很轻,

十万个粒子互相碰撞 会立刻变成另一回事。

100 万粒子,每粒子每帧做 20 FLOPs,

那么一帧总共也就 2000 万 FLOPs。

对现代桌面 GPU 而言,这根本不算大。

kernel 的特点是:

  • ALU 很轻

  • 控制流很平

  • occupancy 往往不错

  • dispatch 非常直接

GPU 很擅长把这种任务铺满执行单元。

粒子数很大时,GPU 反而更容易保持高利用率,因为有足够多的线程去隐藏访存延迟。

所以大量粒子的"便宜",并不只是单粒子便宜,还是因为:

总任务形状非常符合 GPU 的吞吐式架构。

每个粒子都要和场景做碰撞,可能要:

  • 采样 depth

  • 采样 SDF

  • 射线检测

  • 查询 voxel/grid

这已经比重力贵很多。

百万粒子哪怕模拟很轻,画出来也可能很贵。

尤其烟雾、火焰、雾状体这种 overdraw 很容易成为瓶颈。粒子更新轻,前提是它们作为 simulation element 彼此独立;

粒子绘制重,前提是它们作为 translucent surface sample 会在屏幕空间大量重叠。

成本基本按"粒子数"线性增长,接近:

overflow-visible! 复制代码

Plain text
O(N)

因为每个粒子独立更新,不关心它最终投到屏幕上是否重叠。

GPU 的 early-z / depth test 机制。后面的被 depth reject很多 fragment 根本不会进完整 pixel shader

对 translucent particle:

  • 通常不能像 opaque 那样先写深度再把后面全干掉

但对 translucent particle:后面的颜色还要参与混合所以前后层都得算、都得 blend都得 blend

如果一团烟在屏幕中心叠了 30 层,哪怕它看起来只是"一朵烟",GPU 可能真的是把那 30 层对应的 fragment 都跑了一遍。

这就是为什么 overdraw 会成为大头。

天灵盖开了的感觉,这个区别现在才意识到

最理想的实时图形状态,确实是"每个屏幕像素只被稳定地着色一次"

也就是你说的那种:结果在逻辑侧尽量收敛,最后映射到屏幕时,接近"分辨率级别的一次性落图"。

这是对的,而且整个现代图形优化几乎都在朝这个方向逼近。

从信息论角度看,最终输出带宽是有限的,而场景内部中间表示往往是远大于输出分辨率的。于是整个图形系统天然会出现一个问题:

哪些中间复杂度是必须保留到最后的,哪些应该尽早消掉?

Pixel shading,如果按 GPU pipeline 的语义讲,确实就是:

某个 rasterized fragment 已经通过到达 fragment/pixel stage,GPU 开始执行对应的 pixel shader,用来求这个 sample/fragment 的颜色、透明度或其他输出。

所以你说"每个都不可避免要写 pixel shader",这个说法在很多具体路径里要分情况:

不是"所有进入 raster 的东西都一定完整执行 pixel shader",而是:

凡是最终没能在 pixel stage 之前被拒绝、合并、替代或降级的贡献,都会在那里付账。

这才是更准确的说法。

这个 primitive / particle / volume contribution 要不要参与当前视图?

这里会发生:

  • culling

  • LOD

  • clustering / binning

  • coarse visibility

  • bounds reject

  • instance reject

第二道门:

它投影后形成的这些 fragments,哪些 actually 值得着色?

这里会发生:

  • early-z

  • hierarchical-z

  • coarse coverage reject

  • stencil/depth reject

  • alpha/mask 的一部分优化

  • coarse test / tile test

第三道门:

真正执行 pixel shader,为 surviving fragment/sample 生成颜色。

你说的 pixel shading 就是第三门。

而我说"最好在 pixel shading 之前收敛",意思是尽量在前两门多解决问题。

Niagara Module Add(模块添加窗口) 的过滤 UI。Niagara 模块资产体系(Script Asset System) 下解决三个问题:模块来源、资产规模和可维护性。

都是属于逻辑端的计算,重点在?我已经理解?

ue 全蓝图节点介绍,了解每个部分的计算占用多少,或者说建立直觉

Render Graph / Frame Graph 系统

Renderer 主调度流程Scene representation(场景数据结构)Scene representation(场景数据结构)。GPU driven pipeline

MeshDrawCommand 体系就是为了减少:

overflow-visible! 复制代码

PSO switch
Root signature change
Descriptor binding

这部分本质是 CPU → GPU 提交架构

做 DX12 / Vulkan / GPU-driven rendering,这一层非常关键。

资深者的角度,--为什么需要编程语言?

人类无法直接规模化编写机器指令

CPU只理解极少量形式的指令,例如:

  • x86 / ARM 指令

  • Load / Store / Branch

  • SIMD / Vector 操作

理论上所有软件都可以直接写机器码或汇编。但问题是:

  • 指令粒度极低(单条指令只做极小操作)

  • 没有结构化表达

  • 无类型系统

  • 无模块化

抽象层:把"计算模型"表达为可组合结构

现代语言实际上在表达三类抽象:

控制流抽象
if / for / coroutine / async

对应底层
branch / jump / stack

数据抽象
struct / class / ECS / SoA

对应底层
memory layout + pointer arithmetic

计算抽象
lambda / template / generics / shader graph

对应底层
function pointer + code generation

语言把这些模式固化,使得复杂系统可以通过组合构建

例如:

Unity DOTS 的 ECS
Component
System
Entity

本质上只是:
SoA memory + iteration

但语言级表达极大降低理解成本。
为什么 ECS 运行更快?

  • 缓存命中率 (Cache Locality) :传统 OOP 对象散落在内存各处,而 ECS 将相同类型的组件数据连续存储在内存块(Chunks)中,CPU 访问时能极大地减少 Cache Miss
  • 并行计算 :由于数据组织规整且逻辑解耦,ECS 天然适合配合 C# Job System 实现多线程并行处理。
  • SIMD 优化 :配合 Burst Compiler,ECS 代码可以被转换为高度优化的机器码,充分利用 CPU 的向量化计算指令。


ECS 在 2026 年的定位更像是一个 "高性能增强包"

  • 特定场景必备:在 RTS、大规模割草游戏或复杂物理仿真中,ECS 是唯一的性能解决方案。
  • 核心包化:到 2026 年,Entities、Collections 等包已成为 Unity 的"核心包"(Core Packages)

++SoA (Structure of Arrays) 的内存布局 加上 高度优化的线性迭代。++
如果用一句话概括 ECS 的底层逻辑,它确实就是

SoA (Structure of Arrays) 的内存布局 加上 高度优化的线性迭代

内存布局: 从 AoS 到 SoA
在传统的 MonoBehaviour (AoS - Array of Structures) 模式下,对象在内存中是这样排布的:

  • [实体A (位置, 旋转, 血量)] ------ [实体B (位置, 旋转, 血量)]
  • 当你只想更新"位置"时,CPU 必须把包含"旋转"和"血量"的整块数据加载进缓存(Cache Line),这造成了大量的带宽浪费Cache Miss

ECS (SoA - Structure of Arrays) 模式下,数据是按组件类型分组存储的:

  • [位置A, 位置B, 位置C...]
  • [旋转A, 旋转B, 旋转C...]
  • Iteration 的优势 :系统(System)在迭代时,CPU 缓存里全是紧凑的"位置"数据。这种线性访问让 CPU 预取器(Prefetcher)工作效率极高,几乎实现了理论上的最大吞吐量。
相关推荐
双叶8362 小时前
(Python)Python爬虫入门教程:从零开始学习网页抓取(爬虫教学)(Python教学)
后端·爬虫·python·学习
天外来鹿2 小时前
Map/Set/WeakMap/WeakSet学习笔记
前端·javascript·笔记·学习
峥嵘life2 小时前
Android16 【GTS】 GtsDevicePolicyTestCases 测试存在Failed项
android·linux·学习
leixj0253 小时前
SVN学习笔记
笔记·学习·svn
毕设源码_廖学姐3 小时前
计算机毕业设计springboot古诗词学习App 基于SpringBoot的中华经典诗文数字化研习平台 SpringBoot框架下的传统诗词文化移动学习系统
spring boot·学习·课程设计
盐焗西兰花4 小时前
鸿蒙学习实战之路-Share Kit系列(7/17)-自定义分享面板操作区
linux·学习·harmonyos
香水5只用六神5 小时前
【RTOS快速入门】07_同步互斥与通信概述
单片机·嵌入式硬件·学习·操作系统·freertos·rtos·嵌入式软件
庭前云落5 小时前
从零开始的Hardhat学习 1| Hardhat 的基本使用、部署智能合约
学习·智能合约
飞Link6 小时前
深度捕捉时序本质:TSTD 异常检测之表示学习(Representation-based)全解析
学习·算法·数据挖掘·回归