
1. 为什么要做UE学习资料整理这件事我接触虚幻引擎大概有六年时间从最早的UE4.18一路用到现在的UE5.x中间换过三台电脑、重装过无数次系统也带过几个刚入行的朋友入门。最开始那两年我踩过的最大一个坑不是学不会材质节点也不是搞不定蓝图而是资料散落各处学到后面忘了前面遇到问题只能重新搜一遍。你大概也有过这种体验B站收藏夹里躺着一百多个教程视频硬盘里存着几十个G的工程文件浏览器书签里塞满了各种文档链接微信收藏里还有别人随手发的截图和代码片段。真到要用的时候一个都想不起来放哪儿了。更麻烦的是UE这个引擎版本迭代快UE4的某些做法在UE5里直接失效网上一半的教程其实是过时的你照着一顿操作结果编译报错然后就开始怀疑人生。所以“UE学习资料整理”这件事本质上不是整理文件而是整理你的知识结构和排查路径。我最终形成的这套体系核心目标有三个第一让我在遇到任何问题时能在三分钟内定位到可用的参考资料第二把零散的碎片知识串成可以复用的模块比如投掷物抛物线、平面反射倒影渐变这类效果整理成一个可插拔的工程模板第三把性能相关的排查经验沉淀成清单而不是每次靠感觉瞎调。这套整理方法适合什么人如果你是完全零基础的小白它能帮你少走弯路避免收藏一堆没用的东西如果你已经做了一两个小项目它能帮你把散落的经验固化下来如果你是团队里的技术负责人这套结构可以直接作为团队知识库的骨架。我不打算讲什么高大上的方法论就是把我自己实际用的一套目录结构、记录习惯和工具链摆出来你能直接抄。2. 资料整理的整体架构与分类逻辑2.1 按照“用的时候怎么找”来分类而不是按来源分类很多人整理资料的第一反应是按来源分B站教程一堆、官方文档一堆、GitHub工程一堆。这个分法在收集阶段没问题但在使用阶段就是灾难因为你遇到问题时脑子里想的是“我要做一个抛物线”而不是“我要找B站的那个视频”。所以我最终的顶层目录是按使用场景来分的一共六类目录名装什么典型内容举例01_环境与安装引擎版本、安装包、依赖、缓存配置UE安装包管理、改缓存目录、DDC设置02_基础概念语言、类型系统、数学、坐标字符串与文本的区别、换行符处理、向量运算03_渲染与画面材质、光照、后处理、反射平面反射倒影渐变、半透明景深、后期材质04_ gameplay与蓝图交互逻辑、物理、AI、玩法投掷物抛物线、策略游戏框架、状态机05_性能与优化帧率排查、内存、Draw Call排查帧率低的原因、Stat命令、Profiler06_工具与工作流插件、脚本、版本管理、自动化Python脚本、命令行打包、Git LFS这个分类的好处是当我遇到“帧率突然掉到30”这个问题时我直接进05目录里面有一个我自己写的帧率排查清单.md按顺序走一遍基本能定位。而当我需要做个抛物线投掷时进04目录里面有工程模板和参数推导笔记。2.2 每个目录内部的“三层结构”光有顶层分类还不够单个目录内部我也固定成三层这是保证“三分钟定位”的关键第一层是索引文件每个目录根下必有一个README.md或_index.md用表格列出这个目录下所有内容的一句话说明和关键词。我不用全文搜索工具就是这个索引文件先扫一眼人脑匹配速度比搜索引擎快。第二层是专题笔记每个具体知识点或效果一个Markdown文件文件名必须是“问题导向”的比如平面反射倒影渐变怎么做.md而不是反射笔记.md。文件名里带上“怎么做”“为什么”“排查”这类动词搜索和回忆都方便。第三层是可运行工程或代码片段每个复杂一点的专题我都会配一个最小可复现工程放在子目录_demo下面。比如抛物线那个我保留了UE5.3的最小工程打开就能看到抛射物的参数和调试线。2.3 为什么要强调“版本标记”这是被坑出来的经验。UE的版本兼容性是真的差一个在UE5.0里工作正常的材质函数到5.3可能就报错。所以我现在所有笔记和工程的命名都强制带版本号比如抛物线_UE5.3.md、半透明景深_UE5.1_已弃用.md。在索引表里我也加了一列“适用版本”用颜色标注绿色是当前主力版本可用黄色是旧版本可用但新版有替代方案红色是已失效。这个习惯帮我省了大量时间尤其是参考别人教程的时候先看版本对不对不对就降低预期别浪费时间。注意UE的小版本之间也可能有破坏性改动尤其是渲染模块。如果你在5.3的工程里打开5.4保存过的资产有可能出现材质丢失引用的情况。我的做法是主力版本只留一个其他版本用独立目录隔离不要混在一起。3. 几个高频专题的深度拆解3.1 字符串与文本的区别这个坑几乎每个人都会踩这是UE里最容易被忽略但又最容易出bug的基础概念。我见过太多人把FString、FName、FText混着用然后出现性能问题或者本地化失效。简单讲清楚三者的定位FString是运行时可变字符串适合拼接、解析、调试输出但它每次修改都会重新分配内存FName是不区分大小写的不可变标识符底层用的是字符串池所以比较和查找极快适合当字典的键、资源名、骨骼名FText是面向本地化的文本它自带命名空间和keyUI上显示的文案必须用它否则多语言切换就废了。我吐血的经验是千万不要在Tick里用FString拼接日志或者构造FName。FString拼接在Tick里跑每一帧都在做堆分配实测在一个中等场景里几十个Actor每帧拼字符串帧率能掉10到15帧。FName的构造更狠它要走一次全局的字符串池查找和加锁多人同屏的情况下这个开销会放大。正确做法是需要频繁输出的调试信息用预分配的缓冲区或者只在按键触发时输出资源引用统一用FName或TSoftObjectPtrUI文案走FText并且养成用LOCTEXT宏的习惯别直接写中文字面量。3.2 换行符处理日志和UI里最容易出岔子UE里换行符这件事看起来小但实际项目里能恶心到你。不同平台的行尾不一样Windows是\r\nUnix系是\n。你在编辑器里写好的多行文本打包到手机上可能显示成一行或者多出奇怪符号。我在处理日志文件解析的时候踩过一次大坑从外部读进来的文本用\n切割结果Windows生成的日志里每行末尾都带着\r导致字符串比较永远不相等排查了半天才发现是行尾问题。处理方法是在解析前统一做一次规范化把\r\n和\r都替换成\n。在UI层面TextBlock的多行显示要注意Auto Wrap Text和Wrap Text At这两个属性。如果你的文本来自FText且包含换行记得在文本里用真实的换行字符而不是\n字面量。我在本地化表格里填文案时习惯用\n的转义写法导入后引擎会自动转成换行但如果你直接在代码里写TEXT(第一行\n第二行)这个\n是被转义的能正常工作容易混淆的是从CSV导入的情况需要确认导入设置里的转义处理。3.3 改缓存目录这个操作能救你的C盘UE的派生数据缓存DDC默认放在系统盘的用户目录下一个中型项目跑一段时间后这个目录轻松涨到几十个G。我的C盘就是这么被撑爆过一次系统卡到没法用。改缓存目录的方法分两层。第一层是引擎全局的DDC在引擎目录/Engine/Config/BaseEngine.ini里找到[DerivedDataBackendGraph]段修改Path指向一个大容量盘。但直接改BaseEngine.ini不推荐因为引擎升级会被覆盖正确做法是在项目目录下的Config/DefaultEngine.ini里加覆盖段或者在Engine/Config/UserEngine.ini里配置这个文件不会随升级丢失。第二层是项目级的缓存也就是项目目录/Saved和Intermediate这两个目录才是真正随项目膨胀的。我的做法是把整个项目放在大容量SSD上然后用目录链接的方式把Saved映射到另一块盘。不过链接这种方式在团队协作里要小心不同机器路径不一样会造成混乱个人开发随便用。还有个更省心的办法是直接改环境变量UE-LocalDataCachePath和UE-SharedDataCachePath让引擎把DDC放到你指定的位置。这个方式对所有项目和引擎版本都生效改一次就行。实测下来把DDC放到NVMe盘上首次打开大项目的时间能从十几分钟降到三四分钟。提示改DDC路径后第一次启动项目会重新生成缓存所以要预留足够时间和空间。另外网络共享的DDC在多人协作时能省很多重复编译时间但需要保证网络稳定否则会出现缓存读取失败导致编辑器卡死。3.4 平面反射倒影渐变效果好看但性能要吃透平面反射Planar Reflection做水面或者地面积水的倒影效果比屏幕空间反射SSR干净得多因为它不依赖屏幕内已有的像素不会出现边缘拉伸断裂。但它贵本质上是要把场景从反射平面的视角再渲染一遍。我做倒影渐变的核心思路是先用Planar Reflection Capture拿到干净的反射然后在材质里混合一层基于距离或视角的渐变遮罩让倒影随着距离变远或视角变斜逐渐淡出过渡到基础水面颜色。渐变遮罩可以用世界坐标的Z轴距离做lerp也可以用摄像机向量和反射平面法线的点积做菲涅尔式的边缘衰减。性能上要注意几点。Planar Reflection Capture的分辨率是性能大头我一般从512开始试能接受就不往上加1080p的反射贴图在移动端基本别想。反射只影响指定平面要确保Capture的平面范围刚好覆盖水面开太大等于白渲染。还有反射里的场景复杂度可以单独控制在Capture设置里关掉不需要的图层比如粒子和小物件。半透明景深这块更微妙。UE的后处理景深默认对半透明材质是无效的因为半透明不写深度。要让半透明物体参与景深得用自定义的后期材质去采样深度或者在材质里手动根据像素深度做模糊近似。我在做水下场景时用过这个技巧代码不长但需要理解SceneDepth和CustomDepth的取用方式以及为什么半透明像素的深度信息要单独处理。4. 玩法与性能两大实战专题4.1 投掷物抛物线参数推导是关键投掷手雷、扔石头这类抛物线运动看起来简单但要做出手感需要认真调参数。UE自带的Projectile Movement组件可以直接用设置好初速度和重力缩放就行但问题是自动计算落点和高亮预测轨迹需要你自己算。我的做法分三步。第一步确定发射初速度v0和发射角度θ这两个决定了射程和飞行时间。水平射程公式是R v0²·sin(2θ)/g在UE里重力加速度g默认是980厘米每二次方秒重力缩放GravityScale可以调整实际重力是980 * GravityScale。第二步用抛体运动方程推算轨迹点在Tick里按时间步进采样位置用DrawDebugLine或Spline画出来这就是预测线。第三步做碰撞检测预测线和场景做射线检测碰到就截断并显示落点标记。实测下来最影响手感的是初速度的曲线。我一般让初速度随蓄力时间做非线性增长蓄力到一半时速度是满值的60%左右这样短按和长按的区别明显但又不至于轻按就扔不出去。重力缩放我建议保持1.0附近微调改太多会让物理表现失真看起来像在月球上扔东西。注意预测轨迹的采样频率不要太高Tick里每帧算几十个点很浪费。我一般固定采样20到30个点间隔根据预期飞行时间动态算。另外预测线只做视觉效果真正的碰撞还是靠Projectile自身的碰撞两者可能有细微偏差要以物理结果为准。4.2 排查帧率低要有清单式的方法帧率问题最怕的就是“感觉哪里慢”然后瞎调。我整理了一套从粗到细的排查流程放在05目录里每次遇到掉帧就照着走。第一步是确定瓶颈类型。用控制台命令stat unit看四个数值Frame总帧时间、Game游戏线程、Draw渲染线程、GPU显卡时间。哪个数值最接近Frame瓶颈就在哪里。如果Game最高就是逻辑或蓝图太慢如果Draw高是绘制调用太多如果GPU高是渲染负载重。第二步针对瓶颈细化。Game线程高用stat game看具体耗时再配合Unreal Insights抓一段看哪个Actor或哪个函数占用最多。Draw线程高用stat scenerendering看Draw Call数量超过两三千就要考虑合并网格、用实例化。GPU高先降分辨率测试如果降分辨率后帧率明显回升就是像素着色或后处理的问题用stat gpu看各个渲染阶段的耗时。我踩过的一个经典坑是一个空场景也跑不满60帧排查半天发现是一个Actor的Tick里在每帧调用GetAllActorsOfClass。这种全场景遍历在Tick里是性能杀手改成事件驱动或者缓存引用后帧率直接从40回到120。所以我的清单里有一条铁律Tick里禁止出现任何遍历场景、字符串拼接、动态分配内存的操作。4.3 策略游戏方向的资料重点在架构而非效果策略游戏和动作游戏的学习重点完全不同。动作游戏吃渲染和手感策略游戏吃的是数据架构和寻路。策略游戏的核心问题有几个大量单位的选中和框选这需要高效的空间查询用八叉树或网格索引比每帧遍历强得多单位移动和寻路UE自带的导航系统在单位数量上百后会出现排队抖动需要做流场寻路或者分层避障回合制或实时的状态管理我用的是数据驱动的状态机加事件总线把游戏逻辑和表现完全分离。我整理策略游戏资料时重点是几个开源策略项目的结构分析以及UE的Mass框架Entity Component System在大量单位场景下的应用。Mass框架处理上万个单位的移动是没问题的但学习曲线陡建议先把传统Actor模式玩熟再上Mass。5. 工具链与工作习惯的沉淀5.1 安装包和版本管理别贪多UE安装包一个版本动辄几十个G我见过不少人电脑里装了四五个版本结果每个都不精。我的建议是主力版本只装一个比如现在就是5.3或5.4另外留一个上一版做兼容测试。安装的时候用Epic启动器可以只装你需要的平台组件比如只做Windows就把Android和iOS的组件去掉能省十几G。安装包本身也要管理。我会把每个版本的离线安装包备份到移动硬盘因为有时候网络环境不好重新下载要很久。备份的时候记录一下版本号和下载日期UE的补丁版本有时会让项目打不开留个后路。5.2 用命令行和脚本减少重复劳动UE的编辑器操作大部分都能命令行化整理资料时把常用命令记下来能省很多重复点击。比如打包、生成项目文件、跑自动化测试都有对应的命令行。我常用的是UnrealBuildTool和RunUAT的几个命令配合批处理脚本一键完成打包。Python在UE编辑器里也能跑用来批量重命名资产、检查资源引用、导出数据表都很方便。我写过一个脚本扫描项目里所有未被引用的资产并列出清理起来很省心。这些脚本我都放在06_工具与工作流目录带上简要说明。5.3 版本控制UE项目的.gitignore很关键UE项目用Git管理如果.gitignore写不好仓库会膨胀到无法维护。必须忽略的目录包括Binaries、Intermediate、Saved、DerivedDataCache这些都能重新生成。二进制资产用Git LFS管理否则仓库很快就几个G。我的经验是纯蓝图项目可以只用Git但一旦有C代码和大量二进制资产最好用Perforce或者Git LFS。团队协作里.uasset的合并冲突几乎无法解决所以资产的所有权要明确避免多人同时改同一个资产。提示UE的资产引用关系复杂删除资产前先用Reference Viewer看引用链直接从磁盘删文件会导致引用它的蓝图报错。整理资料时把“删除资产的标准流程”单独记一条能避免很多返工。6. 常见问题速查与避坑实录6.1 高频问题速查表现象可能原因快速排查方法编辑器卡顿操作延迟DDC未命中实时编译看右下角是否有编译图标检查DDC路径打包后UI文本乱码或单行FText编码或换行符问题检查本地化表格和导入设置材质编译报错版本差异或节点废弃查看报错节点对照版本更新日志帧率突然下降Tick里有遍历或分配用stat game和Insights定位反射出现撕裂边缘SSR屏幕外信息缺失换Planar Reflection或加边缘遮罩半透明物体不参与景深半透明不写深度用CustomDepth或后期材质处理项目打开缓慢缓存丢失或磁盘慢检查DDC位置和磁盘IO安装包体积过大装了多余平台组件用启动器卸载不需要的平台6.2 几个只有踩过才知道的细节第一个是字符串常量的写法。在UE C里能用TEXT()包裹字面量就用别直接写裸字符串否则在不同平台可能有编码问题。而且TEXT()宏在编译期处理性能上比运行时转换好。第二个是换行符在日志里的规范。我现在的习惯是所有写日志的地方统一用LINE_TERMINATOR宏它会根据平台自动选择正确的行尾跨平台项目里这个细节能省很多麻烦。第三个是性能排查要看数据不要看感觉。我早期调性能全靠“感觉这个材质很重”“感觉这个蓝图很慢”结果经常改错地方。后来强制自己每次都用stat命令和Profiler拿到数据再动手效率高了一倍不止。第四个是版本升级前先备份整个项目。UE的版本升级有时会修改资产格式一旦升级后想回退资产可能已经打不开了。我现在的做法是升级前用Git打一个tag或者直接复制一份工程目录。6.3 关于整理节奏的个人体会资料整理这件事最忌讳的就是“等学完了再整理”。我试过集中整理结果发现学的时候随手记的东西才是最有价值的事后整理反而想不起来当时的思考过程。所以我现在是随时记遇到一个问题解决完就花五分钟把过程写下来格式不用讲究关键是记录“问题是什么、怎么排查、最后怎么解决、下次怎么避免”。然后每周花半小时把这一周记的东西归到对应的目录更新索引文件。这个习惯坚持下来一年后你会发现自己有了一个完全属于自己的知识库里面的每一条都是真金白银的实战经验比任何教程都值钱。提示笔记里一定要记“错误路径”也就是你试过但没用的方案。这个信息在下次遇到类似问题时会救你能避免重复踩同一个坑。很多人只记成功方案结果过段时间又走一遍弯路。这套东西说到底没有多高深就是把散落的东西结构化、把踩过的坑记录化、把重复的操作自动化。UE本身足够复杂能在这上面坚持下去的人最后拼的不是谁学得多快而是谁的积累能真正沉淀下来。