重定向器(Redirector)
官方文档对重定向器的描述如下:
在UE4中,移动或重命名一个资源会在此资源的旧位置中留下一个“重定向器”。这样,当前未加载但引用此资源的包将知道在新的位置中的什么位置找到它。
通俗讲:当一个Asset被移动时,并不是所有引用它的Package都知道它移动到哪了,而为了能帮助引用它的Package找到它的新位置,就在原位置留下一个“重定向器”,这样引用它的包会首先找到“重定向器”,随后就会被指引到新的正确位置。
我想,这里最大的疑问就是:什么时候会创建一个“重定向器”?首先,肯定不可能任何时间只要移动Asset就创建。因为,若一个Asset不被任何包引用,那“重定向器”是没有必要的。
本篇就是对“重定向器”的创建逻辑进行观察。
UObjectRedirector
UObjectRedirector
自身的定义十分简单,它的变量只有一个:UObject* DestinationObject
。其他还有少量的接口,详见\Engine\Source\Runtime\CoreUObject\Public\UObject\ObjectRedirector.h
。
/**
* This class will redirect an object load to another object, so if an object is renamed
* to a different package or group, external references to the object can be found
*/
class UObjectRedirector : public UObject
{
// Variables.
UObject* DestinationObject;
...
}
而在其他的地方就会使用:
实验重定向器的创建场景
既然,当一个Asset没有任何引用时,创建“重定向器”是没必要的。那么,当一个Asset有引用时,移动它就必然会创建一个“重定向器”吗?
——答案是否定的。
下面将做实验观察,首先创建一个Asset模型:
它的大小是81K
:
记住这个大小,因为当这个位置变成“重定向器”后,名字不会发生变化,但是大小会变得很小。
会被创建重定向器的场合
创建一个新场景NewMap
,将testMesh
拖入场景中,将会创建一个Actor,它引用了testMesh
。
创建时间为21:20
:
记住这个时间,因为一会儿想要观察一下,看移动testMesh
之后,这个地图会不会发生变化。
然后进入一个空场景,因为我想确保地图testMap
被卸载掉了
将testMesh
移动到新的文件夹里
可以确认在编辑器中已经看不到testMesh
了
但是在Windows浏览器中还可以看到testMesh.uasset
:
只不过他的大小已经变成了2K
,可以知道它已经变成了“重定向器”了
另外,NewMap
的修改时间还停留在21:20
,可见当移动testMesh
时它并没有修改。
没有被创建重定向器的场合
将刚才的NewMap
删除。
下面创建一个引用testMesh
的的Asset,比如:
引用testMesh
:
他的修改时间为21:45
,记住这个时间
和之前一样,移动testMesh
:
此时发现没有创建“重定向器”
然而引用它的资源的修改时间变了,变成了刚才移动testMesh
的时间:21:49
。可见移动的时候它也一并修改了。
观察重定向器的生成逻辑
UObjectRedirector
在UObject::Rename
中创建:
在此处往堆栈上走,可以了解在一种场合下移动Asset为什么会/不会创建重定向器。
例如,在之前实验NewMap
发现创建了重定向器的场合,会发现:
完整的代码逻辑需要花费不少时间研究,不过可以在\Engine\Source\Developer\AssetTools\Private\AssetRenameManager.h
中FAssetRenameManager
的注释上看到这部分的大概逻辑:
/**
* The manager to handle renaming assets.
* This manager attempts to fix up references in memory if possible and only leaves UObjectRedirectors when needed.
* Redirectors are left unless ALL of the following are true about the asset
* 1) The asset has not yet been checked into source control. This does not apply when source control is disabled.
* 2) The user is able and willing to check out all uasset files that directly reference the asset from source control. The files must be at head revision and not checked out by another user. This rule does not apply when source control is disabled.
* 3) No maps reference the asset directly.
* 4) All uasset files that directly reference the asset are writable on disk.
*/
class FAssetRenameManager : public TSharedFromThis<FAssetRenameManager>
FAssetRenameManager
将尽可能地试图修复引用关系,仅在必要的时候才留下UObjectRedirector
。
除非以下所有条件都为true,否则就会留下重定向器:(即如果以下条件都为true,就不会留下重定向器)
- 这个Asset还没有被check进版本控制。(如果版本控制被禁用,则这个条件就不会启用)
- 用户可以并且准备从版本控制中“check out”所有直接引用这个Asset的uasset文件。这些文件必须在“head version”上并且没有被其他用户“check out”。(如果版本控制被禁用,则这个条件就不会启用)
- 没有地图直接引用这个Asset。
- 所有直接引用这个Asset的uasset文件都在硬盘上是“可写”的。
总结
这么看来,“重定向器”其实是一个“下策”。如果可以,UE4编辑器还是想尽量直接修改引用这个Asset的包。如果实在不方便,才留下“重定向器”。
修复重定向器
右键文件夹可以选择“修复文件夹中的重定向器”
随后可以看到重定向器被删除,而引用它的包(这里是NewMap
)也一起被修改。