自由学习记录(134)

别人的 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 后台,所以看这里:

  1. 打开 chrome://extensions/
  2. 开启"开发者模式"
  3. 找到你的扩展 CSDN Quick Paste
  4. 点 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 , the MyPlugin.Build.cs file 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

    1. 创建了 Source/项目名/

    2. 创建了一个项目自己的 Module

    3. 生成了 .Build.cs.Target.cs

    4. 让 UBT 认为这个项目现在是"有代码项目"

    5. 从此 IDE 工程、C++ 编译、UHT 反射生成都会进入这条链

    所以"蓝图项目改成 C++ 项目"本质上不是改一个开关,而是给项目引入自己的 C++ 编译单元和构建规则
    自己的 C++ 编译单元和构建纯蓝图项目没有自己的模块定义声明了一个 Runtime Module,名叫 MyProject。加了 C++.uproject 往往会出现你的项目代码本质上只是和这些 Engine Modules 一起被构建

    *.Build.csModule 的构建规则

    它不是 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 名称不匹配

    比如:

    .uplugin

    复制代码

    Modules:
    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
    Custom

    Anim 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 Target

    ControlRig 的优势是:

    统一控制系统。

    例如:

    复制代码

    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 相关文档也还在:

    结论:

    • 节点视觉分组/一起拖动:现在看的是 Comment Box
    • 参数分组:Group 还在
    • 所以 UE 5.7 里不是没了,而是你现在这个场景里,应该用 Comment,不是找单独的 Group

    如果你愿意,我可以顺手告诉你 UE 5.7 里 Material Editor 里 Comment / Collapse Nodes / Named Reroute 三者分别该怎

    1. 看右侧 Details
    2. 找这个参数的 Group
    3. 填你想要的组名,比如 Surface、Normal、FX
    4. 保存父材质,再回到实例

    这样实例右边就会按你写的组名显示。Epic 的 5.7 API 文档也写得很直接:参数节点有一个 Group 字段,作用就是 "display in MaterialInstance Editor":

    另外两个关键点:

    • 如果你用的不是 Parameter 节点,而是普通常量/贴图节点,是不会出现在实例里的
    • 组名相同的参数会自动并到同一个组里,没有单独"创建组"按钮;组是靠参数的 Group 字段"生成"的
相关推荐
coder_zh_2 小时前
LaTeX 完整学习笔记 -- 几乎涵盖全部使用方法
笔记·学习
71-32 小时前
Android studio的安装下载(Android Studio Panda 1 | 2025.3.1 Patch 1 )
android·笔记·学习·android studio
Alphapeople2 小时前
购买硬件学习推荐
学习
头疼的程序员2 小时前
计算机网络:自顶向下方法(第七版)第四章 学习分享(一)
网络·学习·计算机网络
凉、介2 小时前
深入 LWIP:数据是如何被封装并发送出去的
网络·驱动开发·笔记·学习·嵌入式
云边散步2 小时前
godot2D游戏教程系列二(15)
笔记·学习·游戏·游戏开发
H Journey2 小时前
学习OpenCV之HSV 颜色模式
人工智能·opencv·学习·hsv
菜菜小狗的学习笔记2 小时前
黑马程序员java web学习笔记--项目部署(Linux)
笔记·学习
charlie1145141912 小时前
通用GUI编程技术——Win32 原生编程实战(五)——ListView 控件详解
windows·学习·gui·win32·编程指南