自由学习记录(172)

如果你说的"UE 热更新"是指网络游戏上线后的版本迭代,那先把概念切开:

第一,编辑器里的 C++ Hot Reload / Live Coding ,不是你线上运营要依赖的热更新体系。

第二,线上真正要设计的是两件事:

一件是内容热更新 ,也就是资源、地图、玩法包、活动包的分发与挂载;

另一件是网络兼容与服务端发布 ,也就是客户端和 Dedicated Server 在协议、数据结构、内容版本上的兼容控制。Epic 官方把补丁/DLC/分块下载单独归在 Patching/ChunkDownloader 体系里,而网络兼容则单独由网络版本机制控制。ChunkDownloader 的官方定义就是:从远端下载资源并在运行时挂载使用。官方文档同时把 chunk、Primary Asset Label、Manifest、补丁创建这些都放在同一套内容分发链路里。(Epic Games Developers)

对 UE 网络游戏,正确的总体设计不是"一个热更新功能",而是四层:

第 1 层:基础安装包(Base Build)

这里放永远要有的内容:登录、大厅、基础角色骨架、核心 UI、最基本战斗逻辑、必要着色器和默认地图。

它的目标不是"大而全",而是"保证你在没有任何增量包时也能启动、登录、鉴权、进入更新流程"。

在 UE 的内容分发体系里,这通常就是基础包加 Chunk 0,其余内容再按 chunk 拆出去。Epic 官方 chunking 文档就是围绕"把资源组织成 chunks"以及通过 Primary Asset Labels 进行分配来做的。(Epic Games Developers)

第 2 层:可下载内容层(Content Chunks)

这是 UE 最适合做"热更新"的部分。你把内容按业务边界拆成 chunk,例如:

  • chunk 0:登录/大厅/基础英雄/公共材质

  • chunk 10:PVP 地图包

  • chunk 20:PVE 副本包

  • chunk 30:新赛季活动资源

  • chunk 40:高分辨率语音/过场

  • chunk 50:地区语言包

这些 chunk 用 Asset Manager / Primary Asset Label 去管理,不要靠人工散装路径维护。因为一旦进入线上,热更新本质上就是"下载哪个 chunk、挂载哪个 chunk、激活哪个玩法入口" 。官方文档明确把 Primary Asset Label 作为 chunk 组织的重要工具;ChunkDownloader 则要求你把这些打包产物和 Manifest 一起托管到远端。(Epic Games Developers)

第 3 层:玩法开关层(Game Features / Feature Toggle)

只靠下载 pak / utoc / ucac 还不够。网络游戏要的是"可控上线",不是"下载完立刻散落在全局"。

这里最好再套一层 Game Features。Epic 的 Game Features 子系统本身就是用于管理 game feature plugins 的。你的设计应该是:

  • 一个新玩法 = 一个 Game Feature plugin

  • 一个赛季活动 = 一个 Game Feature plugin

  • 一个限时副本 = 一个 Game Feature plugin

然后业务流程变成:

  1. 登录后向版本服请求版本清单

  2. 判断本地缺哪些 chunk

  3. 用 ChunkDownloader 下载并挂载

  4. 挂载成功后,再由 Game Feature 层激活功能

  5. 激活失败可回滚为"已下载但未启用"

这样你的"资源分发"和"玩法生效"是两段式,不会因为一个插件激活失败把整个客户端打崩。Game Features 官方 API 文档里直接把 UGameFeaturesSubsystem 定义为 game features 的管理子系统。(Epic Games Developers)

第 4 层:网络兼容层(Protocol / Version Gate)

这是很多人最容易混掉的地方。
内容可以尽量热更新,协议不要幻想无边界兼容。

UE 官方有独立的网络版本与兼容判断机制,FNetworkVersion 以及 IsNetworkCompatible 这一套就是为"这两个实例能不能联网"服务的。也就是说,客户端和服务端是否能互连,本来就是一个显式版本判定问题,不是靠"都能启动"自动解决。(Epic Games Developers)

所以网络游戏要把更新分成两类:

A. 兼容型热更新

不改网络协议,不改关键复制结构,不改 RPC 签名,不改存档/背包核心 schema。

这类通常包括:

  • 新贴图、新特效、新音频

  • 新地图资源,但地图运行规则不变

  • 新活动 UI

  • 纯客户端表现修正

  • 可选下载包

  • 服务器不感知的本地资源替换

这类可以依赖 chunk 下载 + 挂载 + 功能激活。

B. 非兼容型版本更新

一旦涉及下面这些,基本就应该进入"客户端/服务端协同发版",而不是幻想只热更内容:

  • Replication 字段增删改、语义变化

  • RPC 参数或时序变化

  • Gameplay Ability / Attribute / Prediction 逻辑变化影响网络确定性

  • 存档、背包、战斗结算 schema 变化

  • 物品表/技能表被服务端强依赖且旧客户端无法解释

  • 反作弊、登录鉴权、加密校验升级

这类更新应该让登录服或网关做硬版本门禁 :不兼容就拒绝进入匹配,不要让客户端先连上再在游戏内炸。这个门禁可以基于 UE 的网络版本机制再叠加你自己的 BuildId / ContentVersion / ProtocolVersion。(Epic Games Developers)

所以真正可落地的版本号,建议不要只用一个字符串,而是拆成四个:

AppVersion

应用发行版本。对应商店包或整包安装包版本。

ProtocolVersion

网络协议版本。只要复制/RPC/关键表结构变化,就升级。客户端和服务器是否允许互联,优先看它。

ContentVersion

资源清单版本。决定需要下载哪些 chunk。

FeatureSetVersion

功能开关版本。决定哪些 Game Feature 可以激活。

这样你就能做到:

旧包客户端登录后,发现 AppVersion 还行、ProtocolVersion 也兼容,但 ContentVersion 落后,于是先拉内容;

如果 ProtocolVersion 不兼容,直接要求整包更新或切到旧服务器池。

这就引出网络游戏最关键的一条:

服务端更新,优先用"滚动替换",不要追求进程内原地热替换 C++ 逻辑。

原因很简单。UE 线上 Dedicated Server 的核心风险不在"能不能把 DLL 换进去",而在:

  • 现有连接和世界状态怎么办

  • Actor / Replication state / NetDriver 状态怎么办

  • 内存布局和对象生命周期怎么办

  • 正在运行的 match 怎么迁移

  • 回滚怎么做

所以工程上更稳的做法是:

  1. 先起新版本服务器池

  2. 网关把新玩家导到新池

  3. 老池只跑完现有对局,不再接新流量

  4. 对局结束后回收老池

  5. 如异常,网关切回旧池

这不是 UE 特有,而是网络游戏后端的通用常识;但在 UE 上尤其重要,因为 UE 原生官方文档重点支持的是内容补丁与版本兼容判定 ,不是"线上 Dedicated Server 原地代码热替换"。这一点你在架构上要主动承认。基于官方补丁文档,UE 更擅长的是"比较 cooked 内容、生成 patch、分块托管、客户端下载挂载"。(Epic Games Developers)

你如果问"那一个 UE 网络游戏到底怎么搭",我会给你下面这个结构。

客户端启动流程:

  1. 启动最小基础包

  2. 连接版本服 / 配置服

  3. 拉取版本元数据:AppVersion / ProtocolVersion / ContentManifest / FeatureFlags / CDN URLs

  4. 判断协议兼容

  5. 若兼容,检查本地 chunk 是否完整

  6. 用 ChunkDownloader 下载缺失内容

  7. 校验成功后挂载内容

  8. 激活对应 Game Features

  9. 进入大厅 / 匹配

服务端启动流程:

  1. Dedicated Server 启动时加载固定的服务端版本配置

  2. 对外上报 ProtocolVersion、允许的 ContentVersion Range、启用的 FeatureFlags

  3. 匹配服只把客户端分配给兼容服务器

  4. 若新版本上线,先扩新池,再缩旧池

资源组织原则:

  • 永远不要把所有资产都塞 chunk 0

  • 公共依赖放基础包,强业务内容放独立 chunk

  • 一个玩法单元尽量形成"资源 chunk + Game Feature"闭环

  • 把大体积高清资源、语言包、过场包做成可选下载

  • 地图和该地图强依赖资源尽量同一发布单元,避免跨包缺失

表数据原则:

  • 纯客户端展示表可以跟内容版本走

  • 服务器判定型表必须有 schema version

  • DataTable/PrimaryDataAsset 的字段新增要考虑旧版本解析

  • 最好在表头或元数据里加 DataSchemaVersion,由加载器做兼容分支

  • 不要让旧客户端拿到新服务端强依赖字段却静默失败

网络复制原则:

  • 复制字段、RPC、Ability 网络行为尽量只在整包版本里改

  • 热更新阶段优先做资源与配置,不轻易动复制协议

  • 真要兼容演进,就用"新增字段但保留旧语义"的方式跨一个版本窗口过渡

  • 老协议淘汰前,服务端保留双读/双写或兼容解释层

登录与门禁原则:

  • 登录服负责"版本判定"

  • CDN 负责"内容分发"

  • 游戏服负责"玩法执行"

  • 不要让游戏服既做版本裁决又做大文件分发

失败与回滚原则:

  • 下载失败:停留在大厅更新页

  • 挂载失败:回退到旧内容版本,不激活新 Feature

  • Feature 激活失败:只关闭该 Feature,不影响基础大厅

  • 新服异常:网关停止导流,旧服继续承接

  • Manifest 出错:立刻切回上一份 manifest

监控上你至少要打这些埋点:

  • chunk 下载开始/结束/失败码

  • 挂载耗时

  • Feature 激活耗时/失败原因

  • 登录服版本拒绝率

  • 客户端内容校验失败率

  • 新旧服务器池人数占比

  • 因版本不兼容导致的连接拒绝

  • 某个 Feature 开启后崩溃率变化

你还要特别注意一个很现实的问题:

"热更新"在 UE 网络游戏里,最适合热的是内容,不是任意逻辑。

也就是说,最稳的分界线通常是:

可以热:

  • 地图资源

  • 美术资源

  • 本地化

  • 活动入口

  • 部分数据驱动参数

  • Game Feature 级别的可插拔玩法内容

不建议指望无缝热:

  • Dedicated Server 原地 C++ 逻辑替换

  • 大规模复制协议变更

  • 关键移动/战斗预测逻辑改写后仍强兼容旧版本

  • 影响存档和结算一致性的核心系统

如果你要我给一句更硬的结论:

UE 网络游戏的"热更新设计"本质上应该是:
ChunkDownloader + Asset Manager/Primary Asset Labels + Game Features + 版本门禁 + 服务器滚动发布。

而不是把"Hot Reload"当成线上运营方案。(Epic Games Developers)

"UE5.7 网络游戏热更新架构图 + 模块拆分表 + 客户端/版本服/游戏服时序图"

坚持不否认自己,本质上是在保护系统的多样性(Diversity)。如果你彻底同化于那个"黑盒",你将失去作为独立观测者的位置。

系统在未来面对未知逻辑时的弹性

"不兼容性"的长期实验。

官方默认体系。UE 5.7 的打包文档写得很明确,打包出来的 Pak 文件默认在 [Project Name]/Content/Paks 下面;如果启用了分块,输出的 chunk pak 也还是落在这个体系里。也就是说,官方默认关注的是容器文件(.pak / .utoc / .ucas)放在项目内容目录下,而不是把 Content 逻辑上拆成两个同级资源根目录。

Aki

通常像是 项目名目录 、主程序目录,里面放 exe、配置、基础资源、插件资源等;
Paks

则像是 额外的容器资源目录 ,常用于补丁包、分块包、预下载资源、热更新资源,或者启动器/发行层单独管理的内容。

这不是 UE "Content 面板里两个文件夹"的概念,而是 磁盘部署层面的两个资源落点。这是建立在 UE 支持 pak/iostore 容器、分块、补丁和运行时挂载之上的。

UE 本身确实有这些能力:

  1. Pak / IoStore 容器化 :资源不是散文件,而是被打进 .pak,或者在 Zen Loader / IoStore 下打进 .utoc + .ucasEpic Games Developers+1

  2. Chunk 分块 :可以把不同 Primary Asset 规则分到不同 chunk,产出多个包。Epic Games Developers+1

  3. Patch / DLC :官方文档直接讲了补丁和平台无关 DLC,额外容器文件要放到可被运行时发现和挂载的位置。Epic Games Developers+1

  4. 运行时挂载 :底层有 pak 挂载接口与回调,插件管理器也会处理插件内容 pak,因此程序完全可以在启动后再扫描额外目录,把新包挂进来。Epic Games Developers+2Epic Games Developers+2

.sig,在 UE 体系里基本就是:

对应 .pak 的签名文件(signature file) ,用来做完整性校验 / 防篡改验证 ,不是资源内容本体。Epic 的 API 直接把 FPakSignatureFile 描述为"描述 pak .sig 文件内容的结构";项目设置里也明确有 "Enable signing of .pak files to prevent tampering of the data" 这一项。Epic Games Developers+2Epic Games Developers+2

你这张图里一对一出现:

  • pakchunk0-WindowsNoEditor.pak

  • pakchunk0-WindowsNoEditor.sig

意思就是:

这个 pakchunk0 包有一个对应签名文件。

运行时如果启用了 pak signing / signature checking,UE 会用内置公钥之类的签名信息去验证这个 pak 是否被改过。改过、损坏、伪造,都可能导致校验失败。Epic 的 CryptoKeys 设置和 Build Target 里都能看到 pak signing key / enable signing 这套配置入口。Epic Games Developers+2Epic Games Developers+2

  • .pak:真正装资源数据的容器

  • .sig:给 .pak 做验证的签名文件

  • .utoc / .ucas:这是 IoStore 体系,不是传统 pak 签名文件那套命名

  • 这是打包阶段生成的,不是你手动放进去的普通辅助文件。

  • 它通常服务于发行安全,防止玩家或第三方直接改 pak 后仍被程序当成合法资源加载。

  • 它不等于加密。

    签名是"证明没被改",加密是"让别人不好读内容"。UE 的 Crypto 设置里这两套是相关但不同的开关。

  • 常见标题格式
    Neon Genesis Evangelion: The Ending Explained
    EVA Mythology Explained.

  • 特点:主要通过整理琐碎的信息,帮助观众看懂隐晦的剧情(比如《EVA》中的人类补完计划)。

Video Essay
"视频论文"是英文社区中一种非常成熟的类型,解说者通常会像写论文一样,针对某个观点进行严密的论证和叙述。
如果解说涵盖了《EVA》从 1995 年 TV 版到新剧场版几十年的全系列内容,这种回顾性视频被称为 Retrospective

  • 常见标题格式The Complete Evangelion Retrospective.

Iceberg Explained
这是近几年在 YouTube 上极火的一种形式,称为"冰山图解说"。

  • 特点:将知识点分层,从大众皆知的浅层信息(冰山尖端)一直讲到极度核心、阴谋论或都市传说级的深层信息(冰山底部)。对于世界观庞大的《EVA》来说,Iceberg videos 非常受欢迎。

Recap
如果视频主要功能是帮你快速复习剧情(比如在看新剧场版前快速过一遍旧版),则称为 Recap

  • 常用词Everything you need to know before watching Evangelion: 3.0+1.0.

玩梗(Meta-commentary),直接致敬了《新世纪福音战士》(EVA)新剧场版的官方英文片名。
带有括号的写法,其核心含义是 "二元性"与"不确定性"

  • 官方致敬: EVA 新剧场版前三部的官方英文名分别是:
    • 1.11: You Are (Not) Alone(你(不)是孤独一人)
    • 2.22: You Can (Not) Advance(你(不)能前进)
    • 3.33: You Can (Not) Redo(你(不)能重来)
  • 到底好还是不好: 这种写法的精妙之处在于它同时包含了两种相反的观点
    • 读括号里的词: 是否定。表示这些电影不好,或者无法实现标题所说的目标(比如"不能重来")。
    • 忽略括号里的词: 是肯定。表示这些电影好,或者传达了一种积极的愿景(比如"你是孤独的"但最终发现"你不是")。

为什么要这么写?
在视频标题 The Evangelion Rebuild Movies Are (Not) Good 中,作者故意保持这种 暧昧(Ambiguity)的状态,通常是为了表达以下几种意思:

  1. 电影品质有争议: 暗示这部作品既有极好的地方,也有让人难以接受的槽点。
  2. 观点转折: 视频可能先讲电影哪里好,最后再反转说它其实不好;或者反过来,告诉你它虽然有缺点,但其实是一部杰作。
  3. 粉丝共鸣: 作为 EVA 粉丝,一看到这个括注的 (Not) ,就能立刻明白视频是在讨论新剧场版特有的复杂情感和主题逻辑。

  • 涵盖了六大洲不同族裔、职业和性取向者的真实访谈,而在国际社群中获得了极高的声望。
  • 专家推荐 :在主流媒体(如《纽约时报》)关于非单偶制书籍的推荐名单中,它常与《道德浪女》(
    The Ethical Slut
    )等经典著作并列。

"效率"只理解成"批量数据循环的 CPU 效率"时,DOP 常常更强;但 UE 要解决的不只是这一个效率维度,它还要同时服务编辑器、反射、序列化、蓝图、GC、网络复制、资产引用、关卡工作流,所以它的主干长期是对象模型,不是纯 DOP。Mass 才是它在"高规模仿真"场景下补上的数据导向路线。

UE 是"对象系统为主,局部引入数据导向"的引擎。

不是完全排斥 DOP,反而在 5.x 里明确有 MassEntity 这条数据导向框架,官方就直接把它定义成面向高性能、大规模实体计算的 gameplay framework。Mass 的核心概念也是典型 DOP/ECS:FragmentArchetypeChunkProcessor,目标就是让同类数据按块组织并批量处理,改善 cache locality,适合大规模 AI、crowd、traffic 这类场景。Epic Games Developers+3Epic Games Developers+3Epic Games Developers+3

"这个地址对应的数据,现在是不是已经在 L1/L2/L3 里了?"

如果在,就叫命中。

如果不在,就叫 miss,然后要去更下一层取。

硬件必须利用程序的局部性:

时间局部性:刚访问过的数据,很快还会再访问。

空间局部性:访问了某个地址,很可能也会访问附近地址。

缓存就是拿这两个统计规律下注。命中率本质上是在衡量:

"程序的真实访问模式,有多符合缓存所依赖的局部性假设?"

所以命中率不是语言层的概念,而是"访问模式"和"硬件层级结构"相互作用后的结果。

可以说,miss 不可能被彻底消灭,只能被降低、隐藏、摊薄。

原因分三层。

第一层,是容量限制。

缓存不可能和主内存一样大。L1 只有很小一部分空间,L2/L3 也远小于 DRAM。既然工作集可能大于缓存容量,就一定有数据放不下,于是会出现容量 miss。

第二层,是映射限制。

缓存不是"任意地址随便放"。硬件为了速度,会把地址映射到特定的 cache set。不同地址可能竞争同一个位置,即使缓存总容量还够,也会互相顶掉,这叫冲突 miss。

第三层,是首次访问不可避免。

某个数据你第一次碰它时,它之前还没进缓存。第一次通常就会 miss,这类叫 compulsory miss。除非你提前预取到了,而且预取正好成功,否则第一次天然就可能 miss。

DOP 往往不是"因为它叫 DOP 所以快",而是因为它更容易把数据按 CPU 喜欢的方式排布和遍历,于是更容易得到更高的缓存命中率、更少的分支失败、更好的向量化和预取效果。

一个 cache line 里带进来很多这次根本不用的数据

在"都是扫描"的前提下,差距确实不是"会不会替换旧 cache line",因为两边都会替换;真正差距在于:

不是单纯"一次性填入 vs 多次填入",而是填进来的东西,有多少是马上有用的;以及同一条 cache line 被带进来后,能不能在被挤掉前尽量多用几次。

L1/L2/L3 容量固定,所以不管 OOP 还是 DOP,只要数据量大于缓存,最终都会发生:

  • 旧 cache line 被替换

  • 新 cache line 被载入

性能差异不在"是否发生替换",而在"每次替换到底值不值"。

可以把 cache line 想成一次搬运的最小货箱。

CPU 不是按 4 字节、8 字节一粒一粒去 DRAM 拿,而通常是按一整条 cache line 拿,比如常见 64B。

再往下走一步,你这个问题其实还牵涉到"重用距离"。

什么叫重用距离?

某块数据这次用完,下次再用它之前,中间还会访问多少别的数据。

如果中间插入的数据太多,这块数据很可能已经被挤出 L1/L2/L3 了。

那下次再用时就得重新取。

Simulate Physics 的定义就是:为真时,这个 body 使用物理模拟;为假时,它是"fixed / kinematic",也就是按你告诉它的位置去移动。另外,静态网格要能模拟,前提是该 Static Mesh 资产里有简单碰撞;骨骼网格则需要 Physics Asset。

这个组件对应的 BodyInstance 被标记为"由物理系统驱动",不再只是一个普通的 SceneComponent 变换节点。

https://dev.epicgames.com/documentation/unreal-engine/API/Runtime/Engine/FBodyInstance#functions

FBodyInstance 不是"直接代表组件"或者"直接代表资源"的层,它更像是 组件侧的单个物理体实例句柄/状态容器 。所以它那一页的大多数函数,本质上都在和下面几层交互:UPrimitiveComponentUBodySetup / PhysicsAssetFPhysScene/Chaos、碰撞过滤与查询系统、约束/焊接体系,以及少量同步到游戏线程与网络状态的桥接层。

UPrimitiveComponent 上有一个 BodyInstance

官方描述就是持有一个带多个 shape 的单个 rigid body"

一个 BodySetup 会被多个 BodyInstance 共享

FBodyInstance::InitBody 也直接说明了:它是"根据给定的 BodySetup 初始化一个单独刚体"

组件给出拥有者与生命周期,BodySetup 给出碰撞几何与默认物理配置,FBodyInstance 负责把它们实例化成世界里的一个物理 body。

按"它在和 UE 的什么部分交互"来拆,这页函数第一大类是在和 物理世界 / Chaos 刚体求解器 交互。比如 AddForce 这类函数

摘要就是"给 body 添加自定义力和扭矩";

不是普通组件属性读写,而是在改动物理线程里那个刚体的受力与运动状态。

物理系统文档说明其主要物理系统是 Chaos,FPhysScene_Chaos 也被定义为构建自定义模拟时使用的低层 Chaos scene,

UBodySetup 官方说明它包含与单个资源关联的全部 collision information,还包含 collision response、collision trace flag、physical material、simple/complex collision 等默认设置;

FBodyInstance 页面的搜索摘要里能看到 OverlapMulti 这类函数,这说明它不只是"保存状态",还直接参与 overlap/query。

  • 碰到 UObject / Actor / Component / Blueprint:先默认 Game Thread。

  • 碰到 SceneProxy、渲染命令、RHI:先默认 Render/RHI Thread。

  • 碰到 Tasks, ParallelFor, TGraphTask:默认是 worker threads 上的任务系统。

  • 碰到 Chaos 刚体、碰撞、场、求解器:默认要考虑 Physics Thread。

这个框架比死记"某个类属于哪个线程"更可靠。Epic Games Developers+3Epic Games Developers+3Epic Games Developers+3

Event Hit

This event will execute as long as the collision settings on one of the Actors involved have Simulation Generates Hit Events set to true.

If you are creating movement using Sweeps, you will get this event even if you don't have the flag selected. This occurs as long as the Sweep stops you from moving past the blocking object.

单机(Standalone)时:

  • 只有一个游戏实例在跑。

  • 这个实例既是"本地玩家看到的画面",也是"权威游戏逻辑的持有者"。

  • 所以文档才说本地 client 被视为 server。Event Any Damage 会在这个本地实例里执行。Epic Games Developers+1

联机时:

  • 真正的 server 持有权威状态。

  • 客户端只是 server 状态的副本或请求发起方。

  • 因此 Event Any Damage 这类事件不会在普通客户端副本上跑,而是由 server 侧处理。UE 的网络模型本身就是 server-authoritative。Epic Games Developers+2Epic Games Developers+2

更直白的话就是:

"Any Damage 不是一个到处都广播的本地事件,而是一个权威侧事件。单机时,你自己这份实例就是权威侧;联机时,只有服务器那份实例是权威侧。" Epic Games Developers+1


使用内置调试工具(基础篇)
在开发自定义工具前,先掌握官方提供的"神器":

  • Widget Reflector (控件反射器) :通过菜单 Window -> Developer Tools -> Widget Reflector 打开。它可以让你在运行中点击屏幕上的 UI,直接定位到对应的 UMG 资源、查看其嵌套层级和 Slate 属性。
  • Blueprint Debugger : 可以在 UI 蓝图的事件(如 Click, Construct)上打断点,观察变量值的变化。

BeginPlay 前后完成注册Sphere 创建 bodybody 进入 Chaos重力让它产生速度物理步进计算新位置结果同步回 Sphere 组件渲染看到它下落/碰撞如果开了 Simulation Generates Hit Events,则碰撞时还能触发 OnComponentHit
试图把所有逻辑都塞进 Construction Script,会遇到以下痛点:

  • 性能爆炸:因为 Construction Script 会在你移动 Actor 时不停触发,如果里面有复杂的循环或计算,会导致编辑器非常卡顿。
  • 无法执行动态逻辑 :你不能在构造脚本里使用 Delay Timeline 或任何需要游戏时钟的操作。
  • 引用安全问题 :在编辑器阶段,有些对象(如 PlayerController 或其他 Actor 的引用)可能根本不存在,强行调用会导致报错。
  • 打包开销:构造脚本生成的变动通常会被序列化到存档中,过度使用会增加资源体积。

业界普遍认可的"好规范"通常是:

逻辑类型 推荐位置 原因
外观与组件设置 Construction Script 让策划/美术在编辑器里能直接看到效果。
数值预计算 Construction Script 减少运行时的计算压力。
事件绑定/监听 Begin Play 确保游戏环境已完全加载。
与玩家交互的初始化 Begin Play 只有游戏开始后才有"玩家"概念。
网络同步逻辑 Begin Play 构造脚本不在客户端/服务端同步流中运行。

相关推荐
阿荻在肝了2 小时前
Agent学习六:LangGraph学习-持久化与记忆一
python·学习·agent
寒秋花开曾相惜4 小时前
(学习笔记)4.1 Y86-64指令集体系结构(4.1.4 Y86-64异常&4.1.5 Y86-64程序)
开发语言·jvm·数据结构·笔记·学习
莹宝思密达4 小时前
【AI学习】 playwright-cli + SKILL 替换 chrom-devTools-MCP
学习
cyr___5 小时前
Unity教程(二十七)技能系统 黑洞技能(下)黑洞状态
学习·游戏·unity·游戏引擎
豆瓣鸡6 小时前
Gradle学习
学习
海绵宝宝的月光宝盒6 小时前
2-非金属材料
经验分享·笔记·学习·其他·职场和发展·课程设计·制造
小饕7 小时前
RAG学习之- RAG 数据导入完整指南
人工智能·python·学习
cyr___8 小时前
Unity教程(二十六)技能系统 黑洞技能(上)基础实现
学习·游戏·unity·游戏引擎
星幻元宇VR8 小时前
VR党建蛋椅|以沉浸式体验推动党建学习方式创新
科技·学习·安全·vr·虚拟现实