Custom Scalers
Вы можете легко расширить систему Web Adaptive Performance, создав собственные скейлеры. Это полезно, если вы хотите динамически оптимизировать специфичные механики: например, уменьшать плотность толпы, отключать тяжелые шейдеры или упрощать ИИ противников при падении FPS.
Архитектура WebAP vs Unity AP
В официальном пакете от Unity создание кастомных скейлеров требует сложной настройки: создания ScriptableObject, связывания настроек через интерфейсы и выбора одного из двух взаимоисключающих воркфлоу.
В WebAP всё работает по принципу Plug-and-Play.
Вам достаточно написать один C#-скрипт, унаследованный от WebScalerBase. Ядро плагина автоматически найдет ваш класс и добавит его в общий список скейлеров в окне Project Settings, где вы сможете включать его и настраивать параметры визуально.
Обучение на примерах
Лучший способ понять, как писать свои скейлеры — посмотреть, как написаны встроенные. Исходный код всех базовых скейлеров (Resolution, Shadows, LOD и др.) находится в вашем проекте по пути:WebAdaptivePerformance/Runtime/Scalers/.
Шаблон кастомного скейлера
Чтобы создать свой скейлер, выполните 3 простых шага:
- Унаследуйте класс от
WebScalerBase. - Задайте параметры по умолчанию в конструкторе (
Target,Visual Impact,Max Level). - Переопределите методы жизненного цикла:
OnEnabled(),OnDisabled()иOnLevel().
IL2CPP Stripping (Критично для WebGL)
При сборке проекта под WebGL компилятор IL2CPP агрессивно вырезает "мертвый" код (Code Stripping). Поскольку плагин создает экземпляры ваших кастомных скейлеров динамически через рефлексию, компилятор посчитает их неиспользуемыми и удалит из билда.
Всегда добавляйте атрибут [UnityEngine.Scripting.Preserve] к вашим кастомным классам. Это гарантирует, что скейлер будет работать в релизной сборке.
Пример: Скейлер качества текстур
Ниже приведен полный пример создания скейлера, который снижает разрешение текстур (Mipmap Limit).
using System;
using UnityEngine;
using GrindsetStudios.WebAdaptivePerformance.Scalers;
// Атрибуты обязательны для отображения в UI (Project Settings) и защиты от вырезания кода (IL2CPP)
[Serializable]
[UnityEngine.Scripting.Preserve]
public sealed class WebTextureQualityScaler : WebScalerBase
{
// Переменная только для сохранения изначальных настроек пользователя
private int _defaultTextureLimit;
public WebTextureQualityScaler()
{
// Указываем, что этот скейлер снижает нагрузку на видеокарту
_target = ScalerTarget.GPU;
// Снижение разрешения текстур сильно бросается в глаза, поэтому High
_visualImpact = ScalerVisualImpact.High;
// Делаем 3 шага деградации текстур: Half (1), Quarter (2), Eighth (3)
_maxLevel = 3;
}
// Вызывается при старте игры или включении плагина
protected override void OnEnabled()
{
// Кэшируем оригинальное значение, чтобы вернуть его при отключении скейлера
_defaultTextureLimit = QualitySettings.globalTextureMipmapLimit;
ApplyScale();
}
// Вызывается при отключении плагина или ручном удалении скейлера
protected override void OnDisabled()
{
// Безопасно возвращаем игру в исходное состояние
QualitySettings.globalTextureMipmapLimit = _defaultTextureLimit;
}
// Вызывается каждый раз, когда Индексатор решает изменить уровень качества
protected override void OnLevel()
{
ApplyScale();
}
private void ApplyScale()
{
// Метод ScaleChanged() пересчитывает масштаб и возвращает true, если он изменился
if (ScaleChanged())
{
// Мы сознательно не используем дефолтное значение для расчетов,
// чтобы избежать конфликтов, если графика уже была на минимуме.
//
// Параметр globalTextureMipmapLimit принимает целые числа:
// 0 (Full), 1 (Half), 2 (Quarter), 3 (Eighth).
// Наш CurrentLevel (от 0 до 3) идеально совпадает с этой логикой.
QualitySettings.globalTextureMipmapLimit = CurrentLevel;
}
}
}Как только вы сохраните этот скрипт, перейдите в Edit -> Project Settings -> Adaptive Performance (Web). Разверните вкладку Scalers, и вы увидите свой Texture Quality в списке доступных модулей.
Оптимизация поиска объектов
Метод OnLevel() может вызываться часто (при срабатывании кулдаунов). Никогда не используйте внутри него тяжелые методы типа GameObject.Find() или GetComponent(). Всегда находите и кэшируйте нужные компоненты в методе OnEnabled().
