Что за флаг?
Кто устанавливал офицальные ассеты от Unity "Starter Assets - Third Person Character Controller" или "Starter Assets - First Person Character Controller" возможно замечал что в настройках проета (Project settings -> Player -> Other settings -> Script Compilation) появляется флаг STARTER_ASSETS_PACKAGES_CHECKED, но зачем он нужен? Давайте разбираться.
Исследуем скрипты
Для иследования был выбран ассет "Starter Assets - First Person Character Controller". Открываем скрипт "ThirdPersonController" и что мы видим:
...
namespace StarterAssets
{
[RequireComponent(typeof(CharacterController))]
if ENABLE_INPUT_SYSTEM && STARTER_ASSETS_PACKAGES_CHECKED
[RequireComponent(typeof(PlayerInput))]
endif
public class ThirdPersonController : MonoBehaviour
{
...
...
if ENABLE_INPUT_SYSTEM && STARTER_ASSETS_PACKAGES_CHECKED
private PlayerInput _playerInput;
endif
...
...
if ENABLE_INPUT_SYSTEM && STARTER_ASSETS_PACKAGES_CHECKED
_playerInput = GetComponent<PlayerInput>();
else
...
По всюду этот флаг используется в паре с флагом ENABLE_INPUT_SYSTEM, хм... интересно. Очевидно что флаг ENABLE_INPUT_SYSTEM отвечает за новую систему ввода, но вот второй флаг зачем он здесь и кто его устанавливает в настройках проекта? Смотрим дальше. Нашелся еще один флаг в скрипте "StarterAssetsDeployMenu.cs", но уже тут он используется один:
...
if STARTER_ASSETS_PACKAGES_CHECKED
private static void CheckCameras(Transform targetParent, string prefabFolder)
{
CheckMainCamera(prefabFolder);
GameObject vcam = GameObject.Find(CinemachineVirtualCameraName);
...
Из кода становиться понятно что он включает работу с кинемашиной. Интересно, значит получается что этот флаг контролирует подключение кода который в свой очередь находиться в двух пакетах "com.unity.inputsystem" и "com.unity.cinemachine". С этим вроде немного разобрались, но всетаки кто устанавливает этот флаг в настройках проекта?
Исследуем файлы проекта
После тщательного обследования файлов ассета, выявлена подозрительная библиотека Assets\StarterAssets\Editor\PackageChecker\StarterAssetsPackageChecker.dll давайте ее отрефлектим:
Hidden text
И что мы тут видим? Наш флажочек STARTER_ASSETS_PACKAGES_CHECKED)
[Serializable]
private class Settings
{
public string EditorFolderRoot = "Assets/StarterAssets/";
public string[] PackagesToAdd = new string[2]
{
"com.unity.cinemachine",
"com.unity.inputsystem"
};
public string PackageCheckerScriptingDefine => "STARTER_ASSETS_PACKAGES_CHECKED";
}
Так, я чувствую что мы уже близко к истине.
Разбираем потроха StarterAssetsPackageChecker.dll
Изучив код этой библиотеки, я пришол к выводу что это - автоматический инсталятор пакетов Unity. Очень интересно! Давайте расскажу как эта штука работает.
Главный метод запускается каждый раз, при "перезагрузки" редактора, о чем говорит аттрибут[InitializeOnLoadMethod]в этом методе идет поиск файлов с именем "PackageCheckerSettings.json", а затем настройки из этого файла мапятся на PackageChecker._settings.
...
[InitializeOnLoadMethod]
private static void CheckPackage()
{
PackageChecker._settings = new PackageChecker.Settings();
string[] files = Directory.GetFiles(Application.dataPath, "PackageCheckerSettings.json", SearchOption.AllDirectories);
if (files.Length != 0)
JsonUtility.FromJsonOverwrite(File.ReadAllText(files[0]), (object) PackageChecker._settings);
...
Давайте взглянем что находиться в файле "PackageCheckerSettings.json", и тут мы видим опять наши пакеты, а также какой-то "EditorFolderRoot":
{
"EditorFolderRoot": "Assets/StarterAssets/",
"PackagesToAdd": [
"com.unity.cinemachine",
"com.unity.inputsystem"
]
}
Вернемся в нашу dll. Далее по коду идет сравнение версий пакетов и их установка с помощью метода private static AddRequest InstallSelectedPackage. И тут же видим нашу заветную строчку, которая задает флаг STARTER_ASSETS_PACKAGES_CHECKED на уровне проекта:
PackageChecker.SetScriptingDefine(PackageChecker._settings.PackageCheckerScriptingDefine);
...
private static void SetScriptingDefine(string scriptingDefine)
{
BuildTargetGroup buildTargetGroup = EditorUserBuildSettings.selectedBuildTargetGroup;
string defineSymbolsForGroup = PlayerSettings.GetScriptingDefineSymbolsForGroup(buildTargetGroup);
if (defineSymbolsForGroup.Contains(scriptingDefine))
return;
string defines = defineSymbolsForGroup + ";" + scriptingDefine;
PlayerSettings.SetScriptingDefineSymbolsForGroup(buildTargetGroup, defines);
}
Теперь стало все понятно, этот флаг фиксирует установку пакетов и при дальнейшем вызове метода CheckPackage() идет проверка, что если флаг установлен то установку пакетов уже не производим. Вауля!!!
if (PackageChecker.CheckScriptingDefine(PackageChecker._settings.PackageCheckerScriptingDefine))
return;
А что насчет строчки "EditorFolderRoot": "Assets/StarterAssets/" из конфига? А тут все просто она указывает на папку с ассетами которым нужно сделать реимпорт после установки пакетов
private static void ReimportPackagesByKeyword()
{
AssetDatabase.Refresh();
AssetDatabase.ImportAsset(PackageChecker._settings.EditorFolderRoot, ImportAssetOptions.ImportRecursive
}
Что в итоге?
Мы можем использовать библиотеку StarterAssetsPackageChecker.dll в паре с файлом PackageCheckerSettings.json в своем проекте для автоматической установки пакетов Unity. Просто закидываем их к себе в папку Editor и добавляем необходимые пакеты в файл конфигурации.
Чтобы я улучшил в библиотеке StarterAssetsPackageChecker.dll так это сделал бы свойство public string PackageCheckerScriptingDefine => "STARTER_ASSETS_PACKAGES_CHECKED" доступным для записи, чтобы можно было задавать произвольное имя флага в своих ассетах. Еще бы добавил итерацию по всем файлам PackageCheckerSettings.json находящимся в проекте, чтобы установить все зависимости, а не производить установку только по первому попавшемуся файлу.
Могу предположить что у каманды Unity это своего рода "заготовка" для будущей автоматизации установки пакетов, поэтому будем надеяться и верить что работа с пакетами станет еще проще и удобней. А также пожелаем Unity чтобы она добавила возможность добавлять scope в файлы манифеста с помощью кода.
Присоединяйтесь к моим соц сетям:
- GitHub: https://github.com/stupenkov
- Linkedin: https://www.linkedin.com/in/stupenkov/
- Instagram: https://www.instagram.com/devcodeunity/