在虚幻引擎5的蓝图中,当你从一个结构体(Struct)变量或者数组/映射/集合中的某个元素拖出连线并选择Get操作,或者直接右键获取变量时,常常会看到两个选项:Get (a copy) 和 Get (a ref)。理解两者的区别,是正确使用蓝图修改数据的关键。
下面我会先用通俗的方式解释它们,然后带你走一个完整的实操案例:修改玩家背包中某个物品的耐久度,你会清楚看到 Get (a copy) 为什么无效,而 Get (a ref) 才能真正改到原数据。
一、这两个节点分别是什么?
-
Get (a copy)
返回这个结构体(或数组元素)的一份独立复制品。你对它进行的任何修改,只影响这份复制品,不会触及原始变量里存储的数据。蓝图默认倾向于使用这个方式,因为它更安全,防止意外修改原数据。 -
Get (a ref)
返回对原始数据的一个直接引用(可读可写)。你通过这个引用对结构体成员的任何修改,都会直接写入到变量本身存储的那份数据里。常用来修改结构体中的某个属性,或修改容器内某个元素的内容,而不需要重新设置整个变量。
注意:如果变量是基本数据类型(整数、浮点、布尔、向量等),Get 节点不存在
(a copy)和(a ref)的区别,因为它们本身就是值类型,你改的都是副本。只有结构体这种复合数据,以及容器(数组、映射、集合)中取出的结构体元素,才会有这个选项。
二、完整使用案例:修改玩家背包物品的耐久度
我们将构建一个简单的场景:玩家身上有一个 Inventory 数组,存放了多个 Item 结构体。我们需要通过蓝图的交互,减少指定物品的耐久度。重点演示 Get (a ref) 的必要性。
2.1 创建一个新的结构体:物品 (Item)
-
打开内容浏览器,右键 → 蓝图 → 结构体,命名为
ST_Item。 -
双击打开
ST_Item,添加以下变量(都为结构体成员):-
ItemName,类型Text,默认值随意。 -
Durability,类型Float,默认值设为100.0。 -
ItemIcon,类型Texture 2D(可选,不影响演示)。
-
-
保存。这样你就有了一个自定义的结构体。
2.2 在角色或游戏模式中创建背包数组
以放在 ThirdPersonCharacter(第三人称角色蓝图)中为例,方便测试。
-
打开
BP_ThirdPersonCharacter(或你自己的角色蓝图)。 -
在左侧变量列表,点击
+新建变量,命名为Inventory。 -
类型选择 结构体 →
ST_Item。然后将它改为数组(点击变量类型旁边的彩色图标,选择数组,会变成Array of ST_Item)。 -
编译蓝图。
2.3 在事件图表中初始化背包数据
我们在 BeginPlay 时塞入几个物品,方便后续获取和修改。
-
进入事件图表。
-
从
Event BeginPlay节点拖出。 -
添加一个
Set Inventory节点(将变量Inventory拖入图表,选择Set)。 -
在
Set节点的输入引脚上,连接一个Make Array节点。 -
在
Make Array里添加几条元素:-
[0]:
ItemName= “铁剑”,Durability= 100。 -
[1]:
ItemName= “木盾”,Durability= 60。 -
[2]:
ItemName= “药水”,Durability= 30。
-
-
连接好执行线,这样游戏开始时背包里就有三个物品。

2.4 使用键盘按键触发“减少第一个物品耐久度”
我们将绑定一个按键(如 F 键),按下时,获取背包中第 0 个物品(铁剑),并让它的耐久度减少 10。
步骤:
-
在图表空白处右键,输入
F,选择键盘事件F(如果没有,可以从“输入”→“键盘事件”→“F”添加)。 -
从
Pressed拉出,这个执行线就是按下 F 键时运行的逻辑。
2.4.1 错误演示:使用 Get (a copy) 修改
我们先演示 Get (a copy) 为什么不行。
-
将变量
Inventory拖入图表,直接选择Get(此时默认是Get (a copy),你从节点名称看不出,但行为是复制)。 -
从
Inventory的数组引脚拖出,搜索Get,会出现两个选项:-
Get (a copy)(返回复制出来的结构体)
-
Get (a ref)(返回引用)
-
-
我们先选 Get (a copy),然后输入索引 0。
-
从这个 Get 节点的输出结构体引脚拖出,选择
Break ST_Item(或右键“拆分结构体”)。 -
现在你有了
Durability引脚,它的值是从数组元素 0 复制出来的耐久度。 -
我们要对它减去 10:将
Durability引脚连到一个float - float节点,然后用 10 减去,再将结果连回去?不对,因为复制出来的结构体无法“存回”数组。要修改原数组,你必须重新设置整个元素。通常做法是:用SET Array Elem把修改后的结构体放回索引 0。-
既然我们是复制品,可以拉出一个
Make ST_Item,把除了Durability外的其他成员原封不动填进去,再把减去 10 的耐久度填进去,然后用SET Array Elem写回数组索引 0。 -
这种做法可行,但非常笨重。如果直接用 Get (a copy) 尝试修改成员,是绝对不可能成功的,因为你没有修改原数组中的元素。
-
让我们实际尝试更直接的修改方法,并感受复制版本的局限:
有些人会误以为可以直接通过 Get 的引脚修改结构体成员,但蓝图编辑器不允许将引脚连接到 Break 出来的引脚上作为输出(因为那只是读取)。只有通过 Set Members 或 Set 节点,但 Set Members 在结构体上也需要一个能写的引用。因此 Get (a copy) 出来的结构体,你无法直接修改它的成员,因为没有对应的写节点。
2.4.2 正确做法:使用 Get (a ref) 并修改
这才是案例的核心:
-
同样将
Inventory变量拖入图表,从数组引脚拖出搜索Get。 -
这次选择 Get (a ref) 节点。节点上会显示一个圆形钻石图标,标注为
Get (a ref)。 -
索引填写
0(我们要修改铁剑)。 -
此时这个节点的输出结构体引脚是一个引用。从该引脚拖出,搜索
Set Members in ST_Item节点(这个节点专门用来修改结构体引用的成员)。-
如果搜索不到,可以先拖出
Break ST_Item,然后在Break节点上右键选择 “创建集合成员” 或直接搜索Set Members in ST_Item。
-
-
Set Members in ST_Item会展开所有可修改的成员变量,比如ItemName、Durability、ItemIcon。我们只需要更改耐久度,所以把Durability引脚连接到一个减法运算的结果:当前耐久度 – 10。-
从哪里获得当前耐久度?从同一个
Get (a ref)的输出上再拖出一个Break ST_Item只读分支,得到原始的Durability,然后减去 10,再连到Set Members的Durability输入。注意,Break是只读的,可以并列使用。 -
或者使用
Get Durability节点(如果结构体有单独的 Get 节点)。
-
-
把 F 键 Pressed 的执行线连到
Set Members in ST_Item的执行输入端。 -
现在,游戏运行时按下 F,会直接修改数组索引 0 的物品耐久度,不需要重新创建整个结构体,也不需要用
Set Array Elem写回,因为Get (a ref)直接操纵了数组中的那个元素。
下面用简化的节点连接示意:
[Pressed F] -> [Set Members in ST_Item]
Target (struct ref) <-- Get (a ref) [0] from Inventory array
Durability = (Get (a ref) -> Break ST_Item -> Durability) - 10
2.5 验证效果
你可以快速验证修改是否生效:
-
在 Event Tick 或按下另一个键(如 G)时,将
Inventory数组的Get (a copy)和打印节点连接,打印索引 0 的耐久度。 -
按下 F 之前打印一下,再按下 F 之后打印一下,就能看到耐久度减少了 10。如果用
Get (a ref)修改,则会看到变化;若改用Get (a copy)加上复杂替换逻辑(但你没替换的话),则不会变化。
调试技巧:把鼠标悬停在蓝图的
Get (a ref)节点上,会出现提示“这是个引用,修改会直接影响源数据”。
三、在自定义函数或宏中使用引用传递
除了上面直接在事件图使用,Get (a ref) 的行为也用于函数参数传递。当你在一个函数里需要修改传入的结构体,必须把输入参数勾选 Pass-by-Reference。这时对应的蓝图节点会显示 Get (a ref) 样式。
操作步骤演示:函数直接修改结构体成员
-
在角色蓝图中新建一个函数,命名为
ReduceItemDurability。 -
在函数的细节面板,添加一个输入参数
ItemRef,类型为ST_Item,并勾选Pass-by-Reference(引用传递)。 -
在函数图表中,从参数
ItemRef拖出,自动会变成Get (a ref)样式的节点。 -
后面操作和刚才一模一样:拖出
Set Members in ST_Item,把耐久度减去多少。 -
在主事件图中,只需要调用该函数,并把
Inventory数组的Get (a ref)引用传入,函数内部就会直接修改数组中的元素。
这样更清晰、模块化,也避免了到处放 Get (a ref) 导致的混乱。
四、总结与常见陷阱
| 情况 | 使用方式 | 能否修改原数据? |
|---|---|---|
| 从数组/映射/集合获取结构体元素,然后修改成员 | 必须使用 Get (a ref) |
✅ 可以 |
| 从数组获取结构体元素,只读取不修改 | Get (a copy) 即可 |
不修改所以无影响 |
| 从普通结构体变量(非容器元素)获取并修改成员 | 该变量本身就可以直接 Get 并连 Set Members,因为变量本身是引用。但如果你把变量连到 Get (a copy),就变成复制品了。 |
取决于你选择了 copy 还是 ref |
| 传递结构体到函数,并希望在函数内修改源数据 | 参数勾选 Pass-by-Reference,调用时自动带引用 |
✅ 可以 |
常见错误:
-
以为用
Get (a copy)+Break后直接改某个值就能存回去,实际上什么都不发生。 -
在
For Each Loop遍历数组结构体时,循环体给出的元素默认是复制(除非使用For Each Loop with Break并手动取引用),修改后不写回则无效。要修改数组结构体里的元素,应该使用带索引的For Loop配合Get (a ref),或者在For Each中修改后使用Set Array Elem。
五、蓝图编辑器中的具体操作提示(UE5 界面)
-
查看节点类型:当从数组引脚拖出
Get时,弹出的菜单会直接显示“Get (a copy)”和“Get (a ref)”两个选项,字面意思明确。默认的Get变量节点是复制,但你可以右键节点并选择“转换为获得引用(如果可能)”。 -
识别引用节点:引用节点在引脚上会显示一个空心圆圈图标,而复制节点是实心圆点。颜色也有所不同。
-
结构体直接修改:对于已经存在的结构体引用,必须使用
Set Members in <结构体名>节点进行写操作,不能直接用 Break 引脚反向输入。
掌握 Get (a ref) 的使用,会让你在处理 RPG 背包、技能配置、建筑升级等大量使用结构体数据的功能时,代码更简洁、更高效。
感谢您的来访,获取更多精彩文章请收藏本站。







暂无评论内容