UnrealVersionSelector
是 UE 的一个工具,用来关联 uproject
文件、注册引擎、选择引擎版本、生成解决方案等功能的一个工具。 在对 uproject
文件点击右键时,Switch Unreal Engine Version
等选项就是 UnrealVersionSelector 提供的:
UnrealVersionSelector 的参数
-register
:Add the current directory to the list of installations
-fileassociations
:Update all the settings.
-switchversion
:Associate with an engine label
-switchversionsilent
:Associate with a specific engine label
-editor
:Open a project with the editor
-projectlist
:Open the editor
-game
:Play a game using the editor executable
-projectfiles
:Generate Visual Studio project files
注册 UnrealVersionSelector 如果遇到 uproject
没有文件关联的情况可以使用下列注册表修复文件关联。
保存为.reg
,双击合并即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\.uproject] @="Unreal.ProjectFile" [HKEY_CLASSES_ROOT\Unreal.ProjectFile] @="Unreal Engine Project File" [HKEY_CLASSES_ROOT\Unreal.ProjectFile\DefaultIcon] @="\"C:\\Program Files (x86)\\Epic Games\\Launcher\\Engine\\Binaries\\Win64\\UnrealVersionSelector.exe\"" [HKEY_CLASSES_ROOT\Unreal.ProjectFile\shell] [HKEY_CLASSES_ROOT\Unreal.ProjectFile\shell\open] @="Open" [HKEY_CLASSES_ROOT\Unreal.ProjectFile\shell\open\command] @="\"C:\\Program Files (x86)\\Epic Games\\Launcher\\Engine\\Binaries\\Win64\\UnrealVersionSelector.exe\" /editor \"%1\"" [HKEY_CLASSES_ROOT\Unreal.ProjectFile\shell\run] @="Launch game" "Icon"="\"C:\\Program Files (x86)\\Epic Games\\Launcher\\Engine\\Binaries\\Win64\\UnrealVersionSelector.exe\"" [HKEY_CLASSES_ROOT\Unreal.ProjectFile\shell\run\command] @="\"C:\\Program Files (x86)\\Epic Games\\Launcher\\Engine\\Binaries\\Win64\\UnrealVersionSelector.exe\" /game \"%1\"" [HKEY_CLASSES_ROOT\Unreal.ProjectFile\shell\rungenproj] @="Generate Visual Studio project files" "Icon"="\"C:\\Program Files (x86)\\Epic Games\\Launcher\\Engine\\Binaries\\Win64\\UnrealVersionSelector.exe\"" [HKEY_CLASSES_ROOT\Unreal.ProjectFile\shell\rungenproj\command] @="\"C:\\Program Files (x86)\\Epic Games\\Launcher\\Engine\\Binaries\\Win64\\UnrealVersionSelector.exe\" /projectfiles \"%1\"" [HKEY_CLASSES_ROOT\Unreal.ProjectFile\shell\switchversion] @="Switch Unreal Engine version..." "Icon"="\"C:\\Program Files (x86)\\Epic Games\\Launcher\\Engine\\Binaries\\Win64\\UnrealVersionSelector.exe\"" [HKEY_CLASSES_ROOT\Unreal.ProjectFile\shell\switchversion\command] @="\"C:\\Program Files (x86)\\Epic Games\\Launcher\\Engine\\Binaries\\Win64\\UnrealVersionSelector.exe\" /switchversion \"%1\""
获取所有已注册的引擎 可以使用 IDesktopPlatform::EnumerateEngineInstallations
来获取当前系统中所有从启动器安装、以及用户使用 UnrealVersionSelector
注册的引擎版本。
1 2 TMap<FString,FString> Installations; FDesktopPlatformModule::Get ()->EnumerateEngineInstallations (Installations)
注册引擎 使用 UnrealVersionSelector 注册引擎时,会将注册的引擎路径写入到注册表:
1 HKEY_CURRENT_USER\SOFTWARE\Epic Games\Unreal Engine\Builds
其注册表项的 lpValueName
则是生成的一个 GUID:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 bool FDesktopPlatformWindows::RegisterEngineInstallation (const FString &RootDir, FString &OutIdentifier) { bool bRes = false ; if (IsValidRootDirectory (RootDir)) { HKEY hRootKey; if (RegCreateKeyEx (HKEY_CURRENT_USER, InstallationsSubKey, 0 , NULL , REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL , &hRootKey, NULL ) == ERROR_SUCCESS) { FString NewIdentifier = FGuid::NewGuid ().ToString (EGuidFormats::DigitsWithHyphensInBraces); LRESULT SetResult = RegSetValueEx (hRootKey, *NewIdentifier, 0 , REG_SZ, (const BYTE*)*RootDir, (RootDir.Len () + 1 ) * sizeof (TCHAR)); RegCloseKey (hRootKey); if (SetResult == ERROR_SUCCESS) { OutIdentifier = NewIdentifier; bRes = true ; } } } return bRes; }
UE 并没有直接在 IDesktopPlatfrom
中单独提供 获取用户通过使用 UnrealVersionSelector 注册的引擎列表。 但是在 EnumerateEngineInstallations
中写了从注册表获取 per-user installations
引擎:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 void FDesktopPlatformWindows::EnumerateEngineInstallations (TMap<FString, FString> &OutInstallations) { EnumerateLauncherEngineInstallations (OutInstallations); HKEY hKey; if (RegOpenKeyEx (HKEY_CURRENT_USER, InstallationsSubKey, 0 , KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS) { TArray<FString> UniqueDirectories; OutInstallations.GenerateValueArray (UniqueDirectories); TArray<FString> InvalidKeys; for (::DWORD Index = 0 ;; Index++) { TCHAR ValueName[256 ]; TCHAR ValueData[MAX_PATH]; ::DWORD ValueType = 0 ; ::DWORD ValueNameLength = sizeof (ValueName) / sizeof (ValueName[0 ]); ::DWORD ValueDataSize = sizeof (ValueData); LRESULT Result = RegEnumValue (hKey, Index, ValueName, &ValueNameLength, NULL , &ValueType, (BYTE*)&ValueData[0 ], &ValueDataSize); if (Result == ERROR_SUCCESS) { int32 ValueDataLength = ValueDataSize / sizeof (TCHAR); if (ValueDataLength > 0 && ValueData[ValueDataLength - 1 ] == 0 ) ValueDataLength--; FString NormalizedInstalledDirectory (ValueDataLength, ValueData) ; FPaths::NormalizeDirectoryName (NormalizedInstalledDirectory); FPaths::CollapseRelativeDirectories (NormalizedInstalledDirectory); if (IsValidRootDirectory (NormalizedInstalledDirectory) && !UniqueDirectories.Contains (NormalizedInstalledDirectory)) { OutInstallations.Add (ValueName, NormalizedInstalledDirectory); UniqueDirectories.Add (NormalizedInstalledDirectory); } else { InvalidKeys.Add (ValueName); } } else if (Result == ERROR_NO_MORE_ITEMS) { break ; } } for (const FString InvalidKey: InvalidKeys) { RegDeleteValue (hKey, *InvalidKey); } RegCloseKey (hKey); } }
Launcher 版引擎注册表路径 上面提到,如果非源码版引擎,使用 UnrealVersionSelector 注册时会写入到注册表:
1 HKEY_CURRENT_USER\SOFTWARE\Epic Games\Unreal Engine\Builds
从 EpicGameLauncher 安装的版本则会写入到另一个注册表路径下:
1 HKEY_LOCAL_MACHINE\SOFTWARE\EpicGames\Unreal Engine
其值为(从注册表导出的):
1 2 3 4 Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\EpicGames\Unreal Engine\4.18] "InstalledDirectory"="C:\\Program Files\\Epic Games\\UE_4.18"
UE 提供了方法来得到从 EpicGameLauncher 安装的引擎 (通过IDesktopPlatfrom
接口):
1 2 TMap<FString,FString> Installations; FDesktopPlatformModule::Get ()->EnumerateLauncherEngineInstallations (OutInstallations);
注册编译版引擎的安装路径 UE 提供了UnrealVersionSelector
工具用来选择引擎版本 / 生成 sln 等功能,其也可以用来注册本地的引擎 (非 Launcher 安装的引擎,如自己编译的源码版引擎) 到项目文件的右键 Select Unreal Engine Version...
列表中。 简单分析了一下 UnrealVersionSelector
的代码,它的注册流程如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 WinMain_Func=>start: WinMain Main_Func=>operation: Main(Arguments) RegisterCurrentEngineDirectoryWithPrompt_Func=>operation: RegisterCurrentEngineDirectoryWithPrompt() RegisterCurrentEngineDirectory_Func=>operation: RegisterCurrentEngineDirectory(false) GetEngineIdentifierFromRootDir_Func=>operation: FDesktopPlatformModule::Get()->GetEngineIdentifierFromRootDir(EngineRootDir, Identifier) RegisterEngineInstallation_Func=>operation: RegisterEngineInstallation(RootDir, OutIdentifier) end=>end: End WinMain_Func->Main_Func Main_Func->RegisterCurrentEngineDirectoryWithPrompt_Func RegisterCurrentEngineDirectoryWithPrompt_Func->RegisterCurrentEngineDirectory_Func RegisterCurrentEngineDirectory_Func->GetEngineIdentifierFromRootDir_Func GetEngineIdentifierFromRootDir_Func->RegisterEngineInstallation_Func RegisterEngineInstallation_Func->end
向注册表写入的操作在 FDesktopPlatformWindows::RegisterEngineInstallation
这个函数中。 操作为将注册的引擎目录写入到 HKEY_CURRENT_USER\Software\Epic Games\Unreal Engine\Builds
中的字符串项中。 当右键 Switch Unreal Engine Version...
的时候,会修改 .uproject
文件中的 EngineAssociation
值:
其调用流如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 WinMain_Func=>start: WinMain Main_Func=>operation: Main(Arguments) SwitchVersion_Func=>operation: SwitchVersion(const FString& ProjectFileName) GetEngineIdentifierForProject_fUNC=>operation: FDesktopPlatformModule::Get()->GetEngineIdentifierForProject(ProjectFileName, Identifier) // 获取当前选择的引擎 SelectEngineInstallation_Func=>operation: FPlatformInstallation::SelectEngineInstallation(Identifier) // 弹出选择引擎列表框,当前选择的为默认 SetEngineIdentifierForProject_func=>operation: FDesktopPlatformModule::Get()->SetEngineIdentifierForProject(ProjectFileName, Identifier) // 设置选择的引擎,并写入 uproject 文件 ContentOnly=>condition: Is Content Only Project? GenerateProjectFiles_func=>operation: GenerateProjectFiles(ProjectFileName) end=>end: End WinMain_Func->Main_Func Main_Func->SwitchVersion_Func SwitchVersion_Func->GetEngineIdentifierForProject_fUNC GetEngineIdentifierForProject_fUNC->SelectEngineInstallation_Func SelectEngineInstallation_Func->SetEngineIdentifierForProject_func SetEngineIdentifierForProject_func->ContentOnly ContentOnly(yes)->end ContentOnly(no)->GenerateProjectFiles_func GenerateProjectFiles_func->end
执行项目文件写入的操作在 FDesktopPlatformBase::SetEngineIdentifierForProject
中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 bool FDesktopPlatformBase::SetEngineIdentifierForProject (const FString &ProjectFileName, const FString &InIdentifier) { TSharedPtr<FJsonObject> ProjectFile = LoadProjectFile (ProjectFileName); if (!ProjectFile.IsValid ()) { return false ; } FString Identifier = InIdentifier; if (Identifier.Len () > 0 ) { FString RootDir; if (GetEngineRootDirFromIdentifier (Identifier, RootDir)) { const FUProjectDictionary &Dictionary = GetCachedProjectDictionary (RootDir); if (!Dictionary.IsForeignProject (ProjectFileName)) { Identifier.Empty (); } } } ProjectFile->SetStringField (TEXT ("EngineAssociation" ), Identifier); return SaveProjectFile (ProjectFileName, ProjectFile); }
所以如果你选择了一个项目使用编译版引擎,可以使用文本编辑器打开该项目的 .uproject
文件,可以看到其中的 EngineAssociation
项的值就是注册表中的引擎版本值。
注:UnrealVersionSelector 所支持的命令行参数及其用途在UnrealVersionSelector.cpp#L224 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 int Main (const TArray<FString>& Arguments) { bool bRes = false ; if (Arguments.Num () == 0 ) { bRes = RegisterCurrentEngineDirectoryWithPrompt (); } else if (Arguments.Num () == 1 && Arguments[0 ] == TEXT ("-register" )) { bRes = RegisterCurrentEngineDirectory (true ); } else if (Arguments.Num () == 1 && Arguments[0 ] == TEXT ("-fileassociations" )) { bRes = UpdateFileAssociations (); } else if (Arguments.Num () == 2 && Arguments[0 ] == TEXT ("-switchversion" )) { bRes = SwitchVersion (Arguments[1 ]); } else if (Arguments.Num () == 3 && Arguments[0 ] == TEXT ("-switchversionsilent" )) { bRes = SwitchVersionSilent (Arguments[1 ], Arguments[2 ]); } else if (Arguments.Num () == 2 && Arguments[0 ] == TEXT ("-editor" )) { bRes = LaunchEditor (Arguments[1 ], L"" ); } else if (Arguments.Num () == 2 && Arguments[0 ] == TEXT ("-game" )) { bRes = LaunchEditor (Arguments[1 ], L"-game" ); } else if (Arguments.Num () == 2 && Arguments[0 ] == TEXT ("-projectfiles" )) { bRes = GenerateProjectFiles (Arguments[1 ]); } else { FPlatformMisc::MessageBoxExt (EAppMsgType::Ok, TEXT ("Invalid command line" ), NULL ); } return bRes ? 0 : 1 ; }
解决.uproject 右键生成失败 首先要查看右键菜单所使用的 UnrealVersionSelector.exe
的路径,可以打开注册表:
1 HKEY_CLASSES_ROOT\Unreal.ProjectFile
然后找到 shell\open\command
条目查看 UnrealVersionSelector.exe
的位置(如果没有安装过源码版引擎则默认在 EpicGamesLauncher 的 Binaries 路径下),如:
1 "C:\Program Files (x86)\Epic Games\Launcher\Engine\Binaries\Win64\UnrealVersionSelector.exe" /editor "%1"
然后打开 C:\Program Files (x86)\Epic Games\Launcher\Engine\Binaries\Win64
,将UnrealVersionSelector.exe
设置为以管理员权限启动即可(右键 - 属性 - 兼容性 - 以管理员身份运行此程序)。