选择
UE的官方源码是用git管理的: https://github.com/EpicGames/UnrealEngine
不过项目管理他们更推荐P4(Perforce)
P4 对于代码文本的管理有些蛋疼,很多项目喜欢混合 git、svn、perforce 使用。
编辑器
编辑器右下角就有 Source Control 一栏,连上版本控制后我们可以进行 提交、revert 等功能。 点开设置可以进行连接选项的填写:
源码
由于有这么多种版本控制,ue 统一抽出了接口,位于:
Engine\Source\Developer\SourceControl
,可以重点观察 Engine/Source/Developer/SourceControl/Public/ISourceControlProvider.h
例如 P4 则是实现这一接口:
Engine/Plugins/Developer/PerforceSourceControl/Source/PerforceSourceControl/Private/PerforceSourceControlProvider.h
问题(Perforce)
Submit Content 时会导致有的文件状态被改为问号(NotInDepot)
ue有几次缓存,首先会调用 p4 fstat 命令获取各个文件夹内资产的状态,先记录在中间变量 Records 中(位于文件 PerforceSourceControlOperations.cpp):
接着在 ParseUpdateStatusResults 函数中对这个 Records 做处理,根据各个文件的状态,缓存到 OutStates 中(TArray<FPerforceSourceControlState>
类型):
对于之前在p4服务器被delete的文件(HeadAction 是 delete),会把状态标记为 NotInDepot:
这样做的原因是,不允许再次存在相同文件的 move/delete 操作,很合理…
在处理执行的类文件 PerforceSourceControlProvider.cpp 中,有 GetStateInternal 函数获取文件状态,此时会做一级缓存,存到 StateCache,这是一个文件路径名到 FPerforceSourceControlState 的一个映射, 可以对每次查询状态进行加速,很合理:
|
|
我们会在 GetStateInternal 函数中进行处理:
更新的时候,我们会通过 GetStateInternal 函数得到 StateCache 中对应文件的状态,然后通过 OutStates 中已经拉取的状态去更新:
至此,看下来都没很合理。但是!我们项目组对一个小写文件改为大写文件,之前的小写文件删除上传p4. p4服务器是Linux环境,文件系统中Linux区分大小写,而Windows不分大小写。 p4此时就有这条delete的记录,在上述操作中就会缓存到ue里的 OutStates
然后,我们在ue里查询这个大写文件的状态时,由于 StateCache 这个 TMap 默认是不区分大小写的,这就导致谁后进 map 就会把前面的状态覆盖。
例如本地的这个大写文件状态是 checkout,然后提交查询状态时,map 中的状态又被小写文件的记录覆盖了,从而变成了 NotInDepot …
修复方法:把 StateCache 变成一个大小写敏感的 map,修改方法可以参考:
事实上也可以参考这个文件:Engine\Source\Runtime\Core\Private\Containers\ContainersTest.cpp
其中有类 FCaseSensitiveLookupKeyFuncs ,参考他的写法即可