别人的 Derived Data Cache 你没有
UE shader 编译结果不会存进 Git/项目里,而是存在:
DerivedDataCache
典型路径:
C:\Users\<user>\AppData\Local\UnrealEngine\Common\DerivedDataCache
当你:
-
第一次打开项目
-
或换机器
-
或升级 UE 版本
UE 就必须重新编译全部 shader。
DDC 没有共享
团队项目通常会用:
Shared Derived Data Cache
例如:
\\server\UE-DDC
或者:
DDC Cloud
这样新人打开项目 基本不需要编译 shader。
如果没有共享 DDC,每个人都会重新编译。


Shared DDC(团队服务器)
大型团队通常配置:
\\Server\UE-DDC
或者 UE5 的:
Zen DDC server
这种情况下:
所有开发者
所有项目
共享同一份缓存。
例如:
开发者A编译了 20000 shaders
开发者B打开项目时 几乎不用编译。
UE版本之间的复用
DDC key 里包含:
Engine version
Shader compiler version
所以:
| UE版本 | 是否复用DDC |
|---|---|
| 5.3 → 5.3.2 | 基本复用 |
| 5.3 → 5.4 | 大量失效 |
| 5.4 → 5.5 | 基本重建 |
因为 shader compiler 可能变化。
DDC实际体积
UE5项目(Nanite + Lumen)典型:
| 项目规模 | DDC |
|---|---|
| 小项目 | 10--20GB |
| 中型项目 | 50--150GB |
| 大型项目 | 200GB+ |
DDC 会随着你打开不同项目不断增长。
触发快捷键时,当前活动标签页是 chrome://... 页面,chrome.scripting.executeScript 不能注入到这类受保护页面,所以 Promise 直接抛错了。我要把 background.js 补上 URL 白名单判断和统一的异常兜底,避免这种页面把后台脚本打红。
一是在执行前过滤 chrome://、edge://、about: 这类不可注入页面,二是把整个命令处理包进 try/catch,避免任何一次注入失败都变成未捕获异常。
Console会打在哪里?
会打在这个扩展自己的后台控制台里,不是普通网页的 DevTools Console。
你这类 MV3 扩展是 service worker 后台,所以看这里:
- 打开 chrome://extensions/
- 开启"开发者模式"
- 找到你的扩展 CSDN Quick Paste
- 点 Service worker 旁边的"检查视图 / Inspect"
console.warn("send-to-csdn failed:", error) 就会出现在那个 DevTools 的 Console 里。
补充一下:
- 如果是 chrome.scripting.executeScript({ func: ... }) 里注入到网页内部的 console.log,那会出现在目标网页自己的 DevTools Console
- 如果是 background.js 顶层的 console.*,那就在扩展的 Service Worker Console
为什么ddc还会增长?不同项目即有共用部分,也有不共用部分的ddc?
,DDC(Derived Data Cache,衍生数据缓存)源资产(如纹理、网格体、材质)派生出的特定平台格式数据的机制
即使两个项目使用 同一份模型或贴图,只要构建条件不同,也会生成新的 DDC 数据。
例如:
TextureA
overflow-visible!
Project1 → BC7 compression
Project2 → Virtual Texture + BC7
就会产生两个不同缓存条目。
第二个原因是 Shader permutation 的指数增长 。
UE 的 shader key 会包含:
-
material graph hash
-
static switch
-
platform
-
shader model
-
feature flags(Nanite / Lumen / VSM / Strata)
一个 material 在不同项目可能生成完全不同的 permutation 集合。
打开过 Android、Win64、Linux、PS5 项目,同一个资源会产生不同的缓存:
DDC默认不会自动删除旧数据 。
UE 的缓存策略是:
overflow-visible!
Append-only cache
只添加,不主动删除。
因此随着你打开越来越多项目,缓存目录会越来越大。
开发者通常 不会把 Project DDC 提交到 Git,因为:
- 可重建
bash
[Request Derived Data by Key]
|
v
+----------------+
| Memory Cache |
+----------------+
|
hit? --+-- yes --> return
|
no
v
+----------------+
| Local DDC |
| AppData/Common |
+----------------+
|
hit? --+-- yes --> load -> promote to memory -> return
|
no
v
+----------------+
| Project DDC |
| <Project>/DDC |
+----------------+
|
hit? --+-- yes --> load -> maybe write back local/memory -> return
|
no
v
+----------------+
| Shared/Server |
| DDC / Zen |
+----------------+
|
hit? --+-- yes --> download -> promote to local/memory -> return
|
no
v
+----------------+
| Rebuild |
| shader/tex/etc |
+----------------+
|
v
write to configured writable backends
|
v
return
Memory Cache
进程内临时缓存,生命周期最短。
Local DDC
本机全局缓存,通常在用户目录下。跨项目复用。
Project DDC
项目目录下的缓存层。是否真在用、用多少,取决于配置。
Shared / Server DDC
团队共享缓存,通常是 NAS 路径或 Zen DDC 服务。
谁先查、谁可写,取决于 backend graph 配置 。
不同项目、不同 UE 版本、不同团队会有不同顺序。
但思路都一样:先查缓存, miss 再构建,再回写。
服务器 DDC 缓存的是"派生数据本身" ,不是"项目 DDC 文件夹内容的镜像"。
比如某个 Shader Key:
SHA(Key: MaterialX + DX12 + SM6 + Lumen + Nanite)
服务器上存的是这个 key 对应的结果,不是"某台机器项目目录里那个 DerivedDataCache 文件夹"。


把插件定义为不直接改引擎源码、但可以扩展 Editor 或 Runtime 的可选组件;
-
明确插件类型
-
建立
.uplugin和模块结构 -
写
Module的启动/卸载逻辑 -
接入你要扩展的系统:菜单、工具栏、Slate、Asset、Blueprint、Subsystem、渲染或 Runtime
-
处理依赖、打包、版本兼容
-
MyPlugin/
├─ MyPlugin.uplugin
├─ Source/
│ ├─ MyPlugin/
│ │ ├─ MyPlugin.Build.cs
│ │ ├─ Public/
│ │ └─ Private/
│ │ ├─ MyPlugin.cpp
│ │ └─ MyPlugin.h
├─ Resources/
├─ Content/
└─ Config/
In
Unreal Engine , theMyPlugin.Build.csfile is a C# script that tells the Unreal Build Tool (UBT) how to compile and link your plugin module . It is essential for defining which other engine modules your plugin depends on to function.Build.cs。这个决定依赖图。 PublicDependencyModuleNames.AddRange(new[]
{
"Core",
"CoreUObject",
"Engine"
}); PrivateDependencyModuleNames.AddRange(new[]
{
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
"UnrealEd",
"ToolMenus",
"LevelEditor",
"Projects"
});具体依赖项该怎么配,Epic 的模块文档和 Module Properties 文档就是官方基准。模块是 Unreal Build Tool 的基本构造单元,属性和依赖都在这里定义。Epic Games Developers+1
真正开始写代码时,入口一般是
IModuleInterface:C++
StartupModule()里做几类事:-
注册菜单和工具栏
-
注册自定义样式/图标
-
注册 AssetTypeActions
-
注册 Details 面板定制
-
注册 Console Commands
-
初始化通信或后台服务
ShutdownModule()做对称清理:-
反注册菜单
-
反注册扩展点
-
释放句柄
-
关线程/关 socket
如果你要做最常见的 Editor 工具插件,标准落地路径其实是:
第一步:插件壳子建起来
直接在 UE 里用 Plugin Wizard 建一个 C++ 插件,选 Editor Toolbar Button 或 Blank Plugin 都可以。
如果只是研究结构,
Editor Toolbar Button模板最快,因为它已经给你好了:-
Module
-
菜单入口
-
Slate 命令注册
-
插件按钮回调
第二步:把"按钮回调"换成你自己的业务层
不要把逻辑全堆在
PluginButtonClicked()里。建议拆成:
-
UI layer:菜单、按钮、面板 -
Command/Application layer:命令分发 -
Domain layer:资产处理、Actor 操作、蓝图操作 -
Infrastructure layer:文件、JSON、HTTP、Socket、MCP
这样你后面不管接本地 CLI 还是 MCP,Editor UI 都不用重写。
自带的 Built-in 插件第三方插件必须先放到项目目录,然后 UE 才会扫描到。插件不会自动启用UE 插件Build Tool 编译Unity拖 DLL 就用
只编译:Development EditorShipping无法使用的。编译是通过 UnrealBuildTool(UBT) .uplugin / .uproject
↓
UBT解析模块
↓
生成 Build.cs 依赖图
↓
调用 MSVC / Clang
↓
生成 DLL / LIB
选项显示为灰色(不可点击),通常是因为当前项目被识别为纯蓝图项目 ,或者系统缺少必要的编译环境。
虚幻引擎不会为没有源代码的项目生成 IDE 工程文件。游戏逻辑全部由 Blueprint VM(Kismet VM)执行 UE 为 非程序员或快速原型开发提供的一种模式

No C++ Targets -> 不需要IDE工程

没有用户自己的 C++ Module 。-
创建了
Source/项目名/ -
创建了一个项目自己的
Module -
生成了
.Build.cs和.Target.cs -
让 UBT 认为这个项目现在是"有代码项目"
-
从此 IDE 工程、C++ 编译、UHT 反射生成都会进入这条链
所以"蓝图项目改成 C++ 项目"本质上不是改一个开关,而是给项目引入自己的 C++ 编译单元和构建规则。
自己的 C++ 编译单元和构建纯蓝图项目没有自己的模块定义声明了一个 Runtime Module,名叫MyProject。加了 C++.uproject往往会出现你的项目代码本质上只是和这些 Engine Modules 一起被构建*.Build.cs是 Module 的构建规则。它不是 C++,是 C# 脚本,由 UBT 读取。
模块依赖UE 的编译不是普通 C++ 编译,而是两阶段:
头文件扫描(UHT) -> 生成反射代码 -> C++ 编译(UBT 调编译器)
它右侧显示的是 Edit in Blueprint,这基本说明:- 这个组件是蓝图类里定义的默认组件
- 不是你在关卡实例上临时加的组件


做成 预编译插件 大多数插件首先是开发资产,不是发行资产。改一次都要重新为目标平台、目标配置、目标引擎版本重新打包。源码模式虽然进项目时更脆,但开发效率更高,也更符合 UE 的工程化习惯。发预编译包,代价很高预编译插件对版本高度敏感



Binaries的位置取决于 它属于哪个编译单元(Module/Plugin/Project) 。在 UE 的构建体系里,每个构建目标都会有自己的 Binaries 目录 。UBT 没生成 DLL。
正常情况下会生成:
UnrealEditor-UnrealMCP.dll
UnrealEditor-UnrealMCP.pdb
插件从未成功编译Module 名称不匹配
比如:
.upluginModules:
Name: UnrealMCP但
Build.cs:public class MCP : ModuleRules
这种会导致模块不生成 DLL。
插件 DLL 名字不是 PluginName.dll,而是:
UnrealEditor-ModuleName.dll
例如:
UnrealEditor-UnrealMCP.dll
所以你要找的是:
Plugins/UnrealMCP/Binaries/Win64/UnrealEditor-UnrealMCP.dll




UE 有三种 Animation Mode:
1. Use Animation Blueprint(最常用)
Animation Mode = Animation Blueprint
Anim Class = ABP_xxx动画由 AnimGraph 驱动:
-
StateMachine
-
BlendSpace
-
IK
-
Montage
2. Use Animation Asset
Animation Mode = Animation Asset
AnimToPlay = Walk / Idle只播放单个动画。
没有 AnimGraph。
3. Custom Mode
通常用于:
-
ControlRig
-
特殊动画系统
-
Runtime控制
你现在的情况可能是:
这个角色 蓝图里已经设置了 AnimBP ,而你是在 实例组件层看。
因为截图右上角显示:
Edit in Blueprint
说明这个 SkeletalMeshComponent 来自:
Base_42 Blueprint
AnimClass 可能在 Blueprint Class Defaults 里设置。
你可以点:
Edit in Blueprint
然后查看:
Mesh → Animation → Anim Class

你这张图里关系是:- 当前打开:M_actor_laevat_body_01
- 它的父级:M_Common_Skin_RainControl_Inst
- 再往上的父级:M_Common_Skin
这三层通常分别意味着:
- M_Common_Skin
- 真正的母材质
- 这里面有材质节点图和核心实现逻辑
- M_Common_Skin_RainControl_Inst
- 一个中间材质实例
- 在母材质基础上预设了一批参数,可能专门加了雨水/湿润控制这类风格
- M_actor_laevat_body_01
- 你当前这个具体角色身体材质实例
- 主要负责做最终项目里的具体参数覆盖
所以这个 Hierarchy 的作用就是帮你看清:
- 这个材质从哪里继承来的
- 真正逻辑在哪一层
- 当前这一层只是改参数,还是自己就是母材质

左边这些勾选项
这是 Show Flags,控制视口里"显示什么、不显示什么"。
比如:
- Grid:地面网格
- Fog:雾
- Decals:贴花
- Skeletal Meshes:骨骼模型
- Static Meshes:静态网格
- Translucency:半透明
- Collision:碰撞可视化
- Navigation:导航数据
- Landscape:地形
- Widget Components:3D UI 组件
本质上是"渲染层开关"。
2. 右边这串列表
这是 Viewport Stats,控制你要不要在视口里显示某类运行/渲染统计信息。
比如:
- FPS
- Memory
- RHI
- SceneRendering
- Unit
以及更细的高级分类:
- AI
- Anim
- Audio
- Chaos
- Niagara
- Sequencer
- 等等
这些一般用于:
- 性能分析
- 渲染调试
- 子系统观察
- 开发排查
也就是说:
- 左边更偏"画面显示哪些内容"
- 右边更偏"叠加显示哪些统计信息"
你现在打开的是:
- Viewport 菜单
- 进入了 Viewport Stats
- 再展开了 Advanced
所以你现在看的是 Unreal 提供的一套视口调试/统计开关,不是你项目自定义的功能。
Unreal 永远是 Z-up,不会变成 Unity 的 Y-up
不是因为 SSS 很强,而是因为 diffuse lobe、spec lobe、AO、rim、shadow softness 共同把脸部 major planes 交代清楚了

SSS 或 profile scattering 的使用是否克制。值得学习的不是"开了没",而是它是否只在耳朵边缘、鼻翼、脸颊薄区、手指等地方产生合理的透光,而不是把整张脸洗成蜡。很多人做皮肤失败,问题不在 SSS 强度,而在于 diffuse、specular 和 subsurface 的能量配比失衡。虹膜深度感是几何实现、法线骗术还是视差;
瞳孔、虹膜边缘、巩膜血丝、湿润边缘有没有控制到"可见但不过分";
眼睑边缘、泪阜、下眼睑湿线是否建立了真实的湿润感;
眼球转动时高光、遮蔽和接触阴影是否自然。

出书吧gpt大人,
它是不是新建项目都会有?
不一定每个项目都一模一样,但:
- UE 模板项目里很常见
- 很多关卡都会放一个 PostProcessVolume
- 尤其是演示、影视、角色展示场景,基本都会有
另外即使你不放 PostProcessVolume,Unreal 也不是完全"没有后处理":
-
引擎本身就有默认曝光和 tone mapping
-
PostProcessVolume 只是给你一个更明确、可控的覆盖入口
-
你的灯光和曝光体系没有做到"全局自然平衡"
-
现在是靠这个 box 里的后处理参数,把画面压回正常
角色展示、小型打光区、摄影棚场景时其实挺常见:
- box 内是专门调好的展示区
- box 外没认真做全局曝光控制
- 所以视觉反差会很大
PPV 这个盒子本身
- 几乎不是性能重点
- 一个 PostProcessVolume Actor 本身开销很小
- 不是因为场景里放了个 box 就变卡
2. 真正耗性能的是里面的效果
比较常见的开销来源:
- Bloom
- Depth of Field
- Motion Blur
- Ambient Occlusion
- Screen Space Reflections
- Chromatic Aberration
- Lens Flare
- Local Exposure
- Color Grading
- Exposure
- 各种高质量后处理链
其中一般更敏感的是:
- Depth of Field
- SSR / Reflections
- AO
- 高质量 Bloom
- 一些电影感镜头效果
3. 你这个场景如果只是基础曝光/调色
那性能影响通常不算大。
如果它还开了:
- 强景深
- 镜头光晕
- 高质量反射
- 大量屏幕空间效果
那就会明显吃 GPU。
less why,way much better things to do
Actor 层 和 Component 层 。UE 的 Details 面板实际上是把 Component 的属性"向上暴露"到 Actor 的 Inspector,所以你会看到很多看似属于 Actor 的属性,其实来自 Component。SkeletalMeshActor
└── SkeletalMeshComponent
右侧 Details 里当前选中的是 SkeletalMeshComponent,只是 UE 把它显示在 Actor 详情页里。
Actor 负责
-
Transform
-
生命周期
-
蓝图逻辑
-
挂载组件
Component 负责
-
渲染
-
Mesh
-
Animation
-
Physics
-
LOD 等
所以你看到 SkeletalMesh、Animation、Physics、Rendering 这些分类,其实都是 SkeletalMeshComponent 的属性。
SkeletalMesh
(模型网格 + 绑定骨骼权重)
Skeleton
骨骼层级定义(骨骼树 + bind pose)
Animation
作用在 Skeleton 上的动画数据
多个 SkeletalMesh 可以共用同一个 Skeleton,例如:
SK_Character_A
SK_Character_B
SK_Character_C
↓
Skeleton这样动画可以复用。
假设你导入一个角色:
SK_AnimeGirl.uasset
内部包含:
Mesh + SkinWeight
并引用:
SK_AnimeGirl_Skeleton
Skeleton 内部结构类似:
root
├─ pelvis
│ ├─ spine_01
│ │ ├─ spine_02
│ │ │ └─ neck
│ │ │ └─ head
│ ├─ thigh_l
│ └─ thigh_r动画文件:
Run.anim
Idle.anim
Jump.anim都是绑定在这个 Skeleton 上。

SkeletalMeshComponent 里有三个核心字段:
Skeletal Mesh
Animation Mode
Anim Class含义:
Skeletal Mesh
→ 使用哪个模型
Animation Mode
Animation Blueprint
Animation Asset
CustomAnim Class
→ 使用哪个 AnimBlueprint



Get Float Channel
这个节点:
Get Float Channel
意思是:
从某个 Control 的 Channel 读取一个 float。
右侧 Details 面板你可以看到:
Control Name : Channel
Animation Type : Animation Channel
Value Type : Float所以这个 Control 其实不是 transform control,而是一个 数值控制器。
用途通常是:
-
表情权重
-
corrective blend
-
material parameter
-
morph target weight
Set Curve Value
然后把这个值写入:
Set Curve Value
Curve : MT_Nose这个 Curve 实际上就是 SkeletalMesh 的 Animation Curve / Morph Curve。
典型 pipeline 是:
Control Rig Control
↓
Get Float Channel
↓
Set Curve Value
↓
Animation Curve
↓
Morph TargetControlRig 的优势是:
统一控制系统。
例如:
UI slider
↓
ControlRig Control
↓
同时驱动
MorphTarget
Bone offset
Material parameter所以 ControlRig 常用来做:
-
facial rig
-
procedural animation
-
runtime rig logic
直接改 MorphTarget 可以:
ControlRig 的 Graph 最终会被编译成:
RigVM bytecode
运行时执行顺序类似:
Execute_ForwardSolve()
{
value = Control.Channel
Curve["MT_Nose"] = value
}整个 RigVM 是一个 解释执行 VM,而不是 Blueprint VM。
优点:
-
更低 runtime cost
-
deterministic execution
-
animation thread 可运行


材质参数分组 ,那个也还在,只是它是在材质参数的 Group 属性里,用于 Material Instance 面板分组显示参数,不是图里这种节点框选分组。5.7 相关文档也还在:
- https://dev.epicgames.com/documentation/en-us/unreal-engine/creating-and-using-material-instances-in-unreal-engine
- https://dev.epicgames.com/documentation/en-us/unreal-engine/BlueprintAPI/MaterialEditing/RenameMaterialParameterGroup
结论:
- 节点视觉分组/一起拖动:现在看的是 Comment Box
- 参数分组:Group 还在
- 所以 UE 5.7 里不是没了,而是你现在这个场景里,应该用 Comment,不是找单独的 Group
如果你愿意,我可以顺手告诉你 UE 5.7 里 Material Editor 里 Comment / Collapse Nodes / Named Reroute 三者分别该怎
- 看右侧 Details
- 找这个参数的 Group
- 填你想要的组名,比如 Surface、Normal、FX
- 保存父材质,再回到实例
这样实例右边就会按你写的组名显示。Epic 的 5.7 API 文档也写得很直接:参数节点有一个 Group 字段,作用就是 "display in MaterialInstance Editor":
- https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Engine/UMaterialExpressionTextureSample-
- https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Engine/UMaterialExpressionTextureCollectionParameter
另外两个关键点:
- 如果你用的不是 Parameter 节点,而是普通常量/贴图节点,是不会出现在实例里的
- 组名相同的参数会自动并到同一个组里,没有单独"创建组"按钮;组是靠参数的 Group 字段"生成"的
-