UE 编辑器提交卡顿:别扫全量资产,只扫 checked-out 文件
January 7, 2026About 2 min
UE 编辑器提交卡顿:别扫全量资产,只扫 checked-out 文件
大项目里在 UE 编辑器打开「提交(Check In)」窗口时会卡很久——严重时要几个小时。根因是 UE 默认会扫描全量资产来构造待提交列表,项目资产一多就爆炸。解法是把「扫全量」改成「只向版本控制服务端要 checked-out 文件列表」。
根因:ChoosePackagesToCheckIn 扫了整个工程
默认路径下,弹出提交窗口会去遍历工程和引擎的全部内容目录,逐个查每个 package 的源码管理状态。资产上万后这一步慢到不可用:
// 默认做法:把整个引擎/工程内容目录都塞进去扫描
// Filenames.Add(FPaths::ConvertRelativePathToFull(FPaths::EngineContentDir()));
// Filenames.Add(FPaths::ConvertRelativePathToFull(FPaths::ProjectContentDir()));
// Filenames.Add(FPaths::ConvertRelativePathToFull(FPaths::ProjectConfigDir()));
// Filenames.Add(FPaths::ConvertRelativePathToFull(FPaths::GetProjectFilePath()));
提交时其实只关心已经 checked out 的文件,扫全量纯属浪费。
修复:只要 opened(checked-out)文件
第一处,给 operation 加上「只取已打开文件」的标记,不再塞全量目录:
// 提交只需要从源码管理 provider 拿 checked-out 文件列表
// 扫描所有文件要花几个小时
StaticCastSharedRef<FCheckIn>(Operation)->SetGetOpenedOnly(true);
SourceControlProvider.Execute(
Operation,
Filenames,
EConcurrency::Asynchronous,
FSourceControlOperationComplete::CreateStatic(
&FSourceControlWindows::ChoosePackagesToCheckInCallback, OnCompleteDelegate));
第二处,原本构造待提交列表要 FindAllPackageFiles 遍历磁盘上所有 package、再逐个 GetState。改成直接从 provider 的已缓存状态里按谓词筛选——避免遍历磁盘:
// 性能:直接从源码管理 provider 拿 checked-out 列表
// 遍历所有 package 会耗费大量时间
TArray<FSourceControlStateRef> StateList =
SourceControlProvider.GetCachedStateByPredicate(
[bIncludeMaps](const FSourceControlStateRef& State) {
return State->IsCurrent()
&& (State->CanCheckIn()
|| (State->IsSourceControlled() && State->CanAdd()))
&& (bIncludeMaps || !IsMapPackageAsset(*(State->GetFilename())));
});
if (StateList.Num() > 0)
{
for (auto StateIter(StateList.CreateConstIterator()); StateIter; ++StateIter)
{
FSourceControlStateRef State = *StateIter;
OutPackages.Add(State->GetFilename(), MoveTemp(State));
}
return;
}
可泛化的方法论
这个坑的通用形态是:UI 交互里做了一次全量扫描,而实际只需要一个很小的子集。判断依据是「用户此刻真正关心的数据范围」——提交只关心 checked-out 文件,那就直接问版本控制服务端要这个列表,或用已缓存状态按条件过滤,而不是遍历磁盘再逐个查状态。全量扫描随资产量线性甚至超线性增长,交互路径上尤其致命。