UE SoftReference浅析
概述
资源路径: /Game/ThirdPersonCPP/Maps/UEDPIE_0_NewMap1.NewMap1:PersistentLevel.TestActor1_2
- 红色/Game: 资源分区,
/Game
为GameContent区域,/Engine
为EngineContent区域,/Plugin
为PluginContent区域
- 紫色/ThirdPersonCPP/Maps表示资源路径
- 蓝色UEDPIE_0_NewMap1表示Package名称
- 黄色NewMap1表示Package内对象名称, 即World.
- 黑色:子对象分隔符, 表明其后面的都是子对象.
- 绿色PersistentLevel表示以NewMap1作为Outer的SubObject, World中的Level.
- 橙色TestActor1_2表示以PersistentLevel为Outer的SubObject, Level内的Actor.
搜寻过程: 通过资源全路径(/Game/ThirdPersonCPP/Maps/UEDPIE_0_NewMap1)找到package(蓝色UEDPIE_0_NewMap1), 通过Package找到World(黄色NewMap1), 通过world找到Level(绿色PersistentLevel), 通过Level找到Actor(橙色TestActor1_2).
查找过程
构造调试环境:
在LevelBlueprint里面添加Resolve Soft Reference
节点,
它会将SoftRef转换成ObjRef.
其中蓝图节点ExpandNode
内的关键函数为:
调试堆栈:
跟随堆栈, 解析关键函数ResolveObjectInternal
,
通过FindObject<UObject>(nullptr, PathString)
根据路径查找对应UObject.
SubObj分隔符:
:
为SubObject分割符, 其表明后面的Obj为SubObject.
而SubObj不会有FindScriptPackageName
查找步骤.
深入函数StaticFindObject
,
发现其调用ResolveName
, 在ResolveName
函数中,
首先将:
替换成..
,
其意思是将SubObject分隔符:
替换成..
.
然后资源路径由/Game/ThirdPersonCPP/Maps/UEDPIE_1_NewMap1.NewMap1:PersistentLevel.TestActor1_2
变成了/Game/ThirdPersonCPP/Maps/UEDPIE_1_NewMap1.NewMap1..PersistentLevel.TestActor1_2
.
找到第一个Package
又将.
作为分隔符, 提取左边字符串,
后得到:/Game/ThirdPersonCPP/Maps/UEDPIE_1_NewMap1
通过FindObject<UPackage>( InPackage, *PartialName )
找到了资源名对应的资源对象.
所以/Game/ThirdPersonCPP/Maps/UEDPIE_1_NewMap1
是全路径资源对象.
通过Package找到其内部的Object
资源路径剩余字符串为NewMap1..PersistentLevel.TestActor1_2
,
根据分割规则(取.
左边字符串)再次分割,
提取字符串为NewMap1
使用函数FindObject<UObject>
,
根据Out
和PartialName
, 找到Outer中的对象.
堆栈:
最终, 根据Outer找到其内部的Obj(NewMap1). 所以,
NewMap1
为Package:/Game/ThirdPersonCPP/Maps/UEDPIE_1_NewMap1
下的Obj.
递归查找
根据上述流程易知:
- 以
NewMap1
为Outer, 根据SubObjectName:PersistentLevel
, 找到SubObject对象. - 以
PersistentLevel
为Outer, 根据SubObjectName:TestActor1_2
, 找到SubObject对象.
总结
冒号的意思
冒号作为SubObject分割符, 表示其后边的名字为SubObj名字,
不会进行FindScriptPackageName
查找.
Package路径
资源名称,
中Package路径/Game/ThirdPersonCPP/Maps/UEDPIE_0_NewMap1
首个Obj对象
第一个.
后边的名称作为第一个对象NewMap1
子对象
:
后的内容全部作为子对象, 用.
分隔, 递归查找.
:PersistentLevel.TestActor1_2