前言

  在 Unreal 引擎中,动画资源导入之后,就无法对其指向的骨骼进行修改了。
  在论坛上上查了一些资料 链接
  大多数人推荐使用 骨骼重定向 来生成新的动画。
  但是旧的动画会被一些 定序器 或者 蓝图 所引用,怎么将这些引用转移到新的 动画 上。

引用替换

  还是参考了上面论坛链接提到的,删除动画文件的时候,如果动画文件存在引用,则可以选一个新的文件进行引用的替换。

alt

  选择一个新的动画文件替换之前的引用。

  不过这个操作其实并不完整,我们可以打开引用查看器查看文件的引用情况。

alt
alt

  之前的旧资源会保留一个 Redirector重定向器 指向新的资源。
  这会导致无法使用就资源的命名了。

alt

  而且这个无法命名还很诡异,因为目录里已经看不到有这个名字的资源了。
  默认 Redirector重定向器 是看不见的,想要看到它需要在过滤标签里面开启它的过滤。

alt

  这就很难受,因为我们替换资源就是希望新的资源和旧的资源在命名上能够保持一致。
  后来又经过我的一通搜索查找之后,发现文件夹的右键菜单有选项可以清理掉当前选中目录下的重定向器。

alt

  执行这个命令删除掉重定向器就可以将新的资源改名为旧的资源了。

Python 自动处理骨骼替换

  既然上面的操作可以手动实现,用代码自动替换问题也不大了~

  首先需要找到替换引用操作的 Python 调用是啥。
  这个函数的名字并不是我所想到的名字,找了好一段时间才找到 链接

  unreal.EditorAssetLibrary.consolidate_assets 这个函数就是我的目标函数
  新资源和就旧资源数组,就可以实现引用替换到新资源上。

  替换成功之后,怎么将 重定向器 清除呢?
  我先从 C++ 的源码入手,看看清理引用的时候,到底是调用了哪些 C++ 函数。

alt

  然而上面截图的调用并没有在 Python API 里面找到相关调用,只能写个蓝图节点来实现 Python 调用。
  调用这个函数,需要获取出需要清理的 重定向器。
  我当时想先从 Python 获取到 Object ,然后直接传到 C++ 里面进行处理。

1
2
3
4
5
6
7
8
# NOTE 引擎内部路径 | 这个路径是我的测试目录路径
destination_path = '/Game/TestAnim'
reg = unreal.AssetRegistryHelpers.get_asset_registry()
ar_filter = unreal.ARFilter(class_names=["ObjectRedirector"], package_paths=[destination_path])
# NOTE 通过 filters 过滤出目录下的 重定向器 | get_assets 获取到的是 AssetData 类型
redirector_list = [redirector.get_asset() for redirector in reg.get_assets(ar_filter)]
print(redirector_list[0])
# LogPython: <Object '/Game/TestAnim/Replace_ThirdPersonWalk.Replace_ThirdPersonWalk' (0x000002CF62C19E80) Class 'ObjectRedirector'>

  上面的代码可以获取出类型为 ObjectRedirector 的对象。
  所以我当时将这个对象传递到 C++ 蓝图里面进行清理。
  但是这样清理会导致清理失败~
  估计 get_assets 这个函数触发了什么东西,导致 Redirector 被占用了。

  后来不得已我只好改成将路径传到 C++ 函数里面,通过 C++ 加载路径获取对象,就可以了。

1
2
3
4
5
6
7
8
9
# NOTE 引擎内部路径 | 这个路径是我的测试目录路径
destination_path = '/Game/TestAnim'
reg = unreal.AssetRegistryHelpers.get_asset_registry()
ar_filter = unreal.ARFilter(class_names=["ObjectRedirector"], package_paths=[destination_path])
# NOTE 通过 filters 过滤出目录下的 重定向器 | get_assets 获取到的是 AssetData 类型
redirector_list = [redirector.object_path for redirector in reg.get_assets(ar_filter)]

# NOTE 清理获取到的 重定向器
unreal.PyToolkitBPLibrary.fixup_referencers(redirector_list)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void UPyToolkitBPLibrary::FixupReferencers(TArray<FString> ObjectPaths)
{
// NOTE source code from FPathContextMenu::ExecuteFixUpRedirectorsInFolder
TArray<UObjectRedirector *> Redirectors;
for (auto ObjectPath : ObjectPaths)
{
UObject *LoadedObject = LoadObject<UObject>(NULL, *ObjectPath, NULL, ELoadFlags::LOAD_None, NULL);
if(LoadedObject){
auto Redirector = CastChecked<UObjectRedirector>(LoadedObject);
Redirectors.Add(Redirector);
}
}

// Load the asset tools module
FAssetToolsModule &AssetToolsModule = FModuleManager::LoadModuleChecked<FAssetToolsModule>(TEXT("AssetTools"));
AssetToolsModule.Get().FixupReferencers(Redirectors);
}

  基本上通过上面的方法就可以清理掉 重定向器,后续将新的资源的名称同步改为就资源名称即可。
  另外补充一下在 Unreal 引擎里面不支持 windows 系统的反斜杠 \ ,使用 os.path.join 拼接的路径很容易出错
  我网上查了之后,可以用 Python 内置的 posixpath 来拼接路径,确保输出的路径使用 斜杠 /

总结

  以上就是 动画资源替换 的操作。
  有相关的问题欢迎联系我交流~