蓝图笔记¶
通信方式 · 命名规范 · 踩坑记录。
游戏实例¶
游戏实例是整个游戏存活期间唯一的全局对象,关掉游戏才销毁。切关卡数据不丢。
项目中的实际用法¶
BP_ChemistryGameInstance 里设了两个变量:
| 变量 | 类型 | 说明 |
|---|---|---|
| 变换人物 | 布尔 | 当前选择的人物(第一人称 / 第三人称) |
| 模式选择 | 枚举 | 教学模式 / 考试模式 |
主菜单选择 → 跨关卡传递:
主菜单 setting_start.uasset 的按钮点击 → 设置游戏实例里的"模式选择" → 场景里的 WBP_TaskPanel2.uasset 读取游戏实例 → 根据值显示对应界面。
人物切换效果:主菜单选择模式时,悬浮在考试或教学模式上分别出现不同的人物预览,点击后锁定该模式的人物。切到实验场景时,游戏实例里存的人物被读出,加载对应人物。
// 主菜单按钮点击:写
获取游戏实例 → 转换为 BP_ChemistryGameInstance → 设置 模式选择(枚举)/ 变换人物(布尔)
// 场景 UI 打开时:读
获取游戏实例 → 转换为 BP_ChemistryGameInstance → 获取 模式选择 / 变换人物 → 决定界面和人物
游戏实例适合放"切关卡不能丢"但"关了游戏不需要保留"的数据。要永久保存用 SaveGame。
蓝图间的通信¶
参考 B 站视频,讲解了四种通信方式。
方式 1:变量直接引用¶
在这个蓝图里创建一个变量,类型选你要找的那个蓝图,然后去关卡里指给它"是哪一个"。
步骤:
- 蓝图一里新建变量 → 类型选蓝图二(对象引用)
- 编译 → 勾选变量的可编辑实例和生成时公开
- 回到关卡 → 选中蓝图一 → 右侧细节面板就能看到这个变量 → 用滴管吸蓝图二
- 蓝图一里拖出这个变量 → 直接调蓝图二的函数或事件
不想勾那两个选项? 把变量类型从"对象引用"改成软对象引用,就可以直接在蓝图默认值里选,不需要去关卡里指。
或者不建变量,直接获取——本项目最常用:
// 场景里只有一个蓝图二时
获取类的Actor(蓝图二) → 调它的函数
// 场景里有多个蓝图二,想指定某一个 → 先给它打标签
// 选中蓝图二 → 细节面板 → 标签 → 添加 "实验器材"
通过标签获取Actor("实验器材") → 调它的函数
获取类的Actor是项目里用得最多的通信方式。不用预先建变量,不用去关卡里指认,写哪算哪,最灵活。
方式 2:事件分发器¶
适合"一件事发生了,通知其他人"。一对多——一个人发广播,多个人收听。
步骤:
- 蓝图一(发广播的)→ 左侧面板 → 事件分发器 → 新建一个,起名
- 拖这个分发器到图表 → 选调用(就是广播出去)
- 蓝图二(收听方)→ 开始运行时先获取蓝图一的引用 → 绑定事件到分发器 → 连到自己的自定义事件
// 蓝图一:发送
事件分发器 OnTaskCompleted → 调用 // 广播:任务完成了
// 蓝图二:接收
开始运行:
获取类的Actor(蓝图一)
→ 绑定事件到 OnTaskCompleted
→ 触发时 → 刷新 UI
方式 3:蓝图接口¶
先建一个蓝图接口资产,里面定义函数名。谁实现了这个接口,谁就必须写这个函数的具体内容。
创建步骤:
- 内容浏览器右键 → 蓝图 → 蓝图接口,起名
- 双击打开 → 默认有一个函数 → 改个名
- 目标蓝图 → 类设置 → 已实现接口 → 添加刚建的接口
- 目标蓝图里会出现接口事件 → 双击实现 → 写具体逻辑
调用方式有两种:
调用方式一:遍历所有实现了接口的 Actor¶
连接:https://www.bilibili.com/video/BV14hJ9z8EvQ/?spm_id_from=333.1387.favlist.content.click&vd_source=b8f35d6b8b01aaa29ccd685ef5fd7b18
适合"找到场景里所有能交互的东西,挨个通知"。
调用方式二:直接对某个 Actor 调接口事件¶
连接:https://www.bilibili.com/video/BV1YVMizfEP5/?spm_id_from=333.1387.favlist.content.click&vd_source=b8f35d6b8b01aaa29ccd685ef5fd7b18
你已经拿到了一个具体的 Actor,不管它是什么类型,直接让它干活。不用写一堆类型转换。
例子:角色按 E 键,跟面前的物体交互。场景里有门(开门)、吊灯(开关灯)、墙(升降)。
第 1 步:建接口
内容浏览器右键 → 蓝图 → 蓝图接口,起名 BPI_Interact。双击打开,里面默认已经有一个函数,改名为 InteractWithPlayer。这里什么都不用写,只声明。
第 2 步:每个物体实现接口
打开门蓝图 → 顶部菜单 类设置 → 已实现接口 → 点添加 → 选 BPI_Interact。
添加后,左侧 我的蓝图 面板里会出现一个 接口 分类,下面有 InteractWithPlayer。右键它 → 实现事件 → 图表里会出现一个事件节点 → 连到开门逻辑。
吊灯、墙同样操作——各自添加接口、各自实现事件、各自连到自己逻辑。
第 3 步:调用
回到玩家蓝图,检测到物体后直接拉线出接口事件:
搜节点时输入 InteractWithPlayer,选带信封图标的那个。
节点对照:
球形重叠检测= Sphere Overlap Actors,数组元素(0)= 取数组第一个。
效果:按 E 键 → 检测到门就开门,检测到灯就开关灯,检测到墙就升降。对方没实现接口的话什么都不发生,不报错。
以后加任何新物体(窗户、抽屉),只需做第 2 步,玩家代码不用改。
不用接口的话,每种物体都得写一段"转换为某蓝图",性能差,而且每加一种就要回来改代码。
什么时候用哪个¶
| 情况 | 用哪个 |
|---|---|
| 我明确知道要找谁,一对一 | 变量引用 |
| 一件事发生了,要通知好几个地方 | 事件分发器 |
| 不同类型的东西,要做同一件事 | 蓝图接口 |
Widget 创建规范¶
控件的创建没有硬性规定必须放 HUD 蓝图里。常见做法是哪个蓝图需要就自己创建:
实际项目中,UI 面板通常在玩家控制器或具体的界面管理蓝图里统一创建,不用 HUD。
数据持久化:SaveGame¶
凡是关了游戏还想保留的数据,都用 SaveGame。 音量、分数、段位、通关进度,套路都一样。
三个节点分工¶
怎么用¶
第 1 步:建 SaveGame 蓝图
内容浏览器右键 → 蓝图 → SaveGame,起名,打开后加变量(比如 Score、MasterVolume)。
第 2 步:存数据
第 3 步:取数据
和游戏实例的区别¶
| 游戏实例 | SaveGame | |
|---|---|---|
| 切关卡 | 还在 | 还在 |
| 关游戏重开 | ❌ 没了 | ✅ 还在 |
| 适合放什么 | 当前临时数据 | 永久设置、存档 |
音量设置关了游戏下次打开还在 → 用 SaveGame,不用游戏实例。
命名规范¶
| 前缀 | 类型 | 示例 |
|---|---|---|
BP_ |
蓝图 Actor | BP_TaskManager1 |
WBP_ |
控件蓝图 | WBP_gameover |
MI_ |
材质实例 | MI_Unlit_Opaque |
E_ |
枚举 | E_PlayMode |
S_ |
结构体 | S_ExperimentRecord |
LS_ |
关卡序列 | LS_YYF |