Использование памяти имеет решающее значение в разработке игр для Android. При разработке игр с использованием Unreal Engine необходимо постоянно анализировать и отслеживать состояние памяти , чтобы соблюдать ограничения по её использованию, предотвращая утечки памяти и чрезмерное выделение памяти.
Экономия памяти за счет сокращения количества перестановок шейдеров.
Удаление неиспользуемых параметров в Lighting или Mobile Shader Permutation Reduction позволяет минимизировать количество перестановок шейдеров. Это значительно уменьшает размер пакета приложения, снижает количество объектов состояния конвейера (PSO) и предотвращает создание неиспользуемых целевых областей рендеринга или фиктивных текстур, что приводит к сокращению памяти во время выполнения и повышению производительности.
Для получения дополнительной информации см. раздел «Различные настройки уменьшения количества перестановок освещения и шейдеров для мобильных устройств» в руководстве по производительности мобильных устройств .
Оптимизация загрузки активов
При загрузке ресурсов с использованием жестких ссылок в память одновременно загружается связанный контент, который даже не используется в игре, что приводит к ненужному потреблению памяти. В частности, при неправильном использовании наследования в Blueprint выделяются ненужные CDO (Class Default Objects) от родительских классов, что приводит к значительной потере памяти. В таких случаях для оптимизации использования памяти следует применять следующие методы.
- Определение кода C++ и разделение данных : Определение основных функций с использованием
UCLASS(Abstract)в коде C++, отделяя их от фактических данных. - Минимизация наследования : выполняйте настройку данных и загрузку ресурсов только в базовых узлах Blueprint.
- Используйте косвенные ссылки : применяйте косвенные ссылки на свойства с помощью
TSoftObjectPtr, чтобы избежать жестких ссылок, и асинхронно загружайте ресурсы только тогда, когда это необходимо во время выполнения. - Меры предосторожности : При использовании асинхронной загрузки ресурсов убедитесь, что проверки на валидность (
IsValid) выполняются во время вызова функции обратного вызова по завершении загрузки, чтобы предотвратить появление висячих указателей или сбои.
Для получения дополнительной информации см. разделы «Использование ресурсов» и «Создание мобильных игр с помощью UE5» .
Интеллектуальные указатели и настройка сборки мусора (GC)
Использование интеллектуальных указателей (таких как TSharedPtr и TWeakPtr ) в процессе разработки на C++ предотвращает появление висячих указателей и утечек памяти. Кроме того, использование TWeakPtr позволяет избежать создания сильных ссылок на объекты, поэтому сборщик мусора не увеличивает счетчики ссылок при сборке объектов. Это предотвращает ненужное сохранение объектов и снижает сложность графа ссылок, который должен пройти сборщик мусора, значительно уменьшая накладные расходы на сборку мусора. В мобильных средах сборку мусора можно эффективно управлять, запуская ForceGarbageCollection во время переходов между уровнями или в периоды бездействия, например, когда нет взаимодействия с пользователем. Кроме того, его можно запускать, когда игра находится в видимом состоянии или в фоновом режиме (например, при вызовах onStop ), гарантируя, что сборка мусора будет выполнена без влияния на активный игровой процесс.
Для получения дополнительной информации см. разделы «Сборка мусора» и «Умный указатель» .
Оптимизация с использованием сжатия таблицы перемещений.
Сжатие таблицы перемещений (Relocation Table Compression) — это метод оптимизации, который сжимает размер таблицы перемещений в ELF-бинарных файлах для уменьшения размера бинарных файлов Android . При minSDKVersion Android 23 или выше поддерживается сжатие таблицы перемещений APS; при minSDKVersion 28 или выше дополнительно поддерживается сжатие таблицы перемещений RELR, что значительно уменьшает размер файла .so. Это не только уменьшает размер загружаемого файла, но и снижает объем памяти, занимаемый mmap файла .so во время выполнения, уменьшая общую нагрузку на физическую память.
AndroidToolChain.cs
if (MinSDKVersion >= 28)
{
Result += " -Wl,--pack-dyn-relocs=android+relr,--use-android-relr-tags";
}
else if (MinSDKVersion >= 23)
{
Result += " -Wl,--pack-dyn-relocs=android";
}
Для применения этой оптимизации убедитесь, что в настройках проекта включена опция "Включить сжатие таблиц перемещения" или переменная bEnableAdvancedBinaryCompression .
Чтобы проверить, правильно ли применено сжатие RELR к бинарному файлу, используйте инструмент llvm-readelf из Android NDK.
llvm-readelf -d libUnreal.so | grep RELR
На практике сборка шаблона ThirdPerson в Unreal Engine и измерение с помощью dumpsys meminfo подтверждают снижение использования PSS и RSS для .so mmap.
| Категория | PSS Всего | Частный Грязный | Частная уборка | Swap Dirty | RSS Всего |
|---|---|---|---|---|---|
| .so mmap Перед сжатием | 170,210 | 24,360 | 141,564 | 0 | 242,204 |
| .so mmap После сжатия | 138,031 | 24,748 | 108,976 | 0 | 210,140 |
Сжатие текстур
Используйте соответствующее сжатие текстур, чтобы уменьшить объем памяти, занимаемый графическими ресурсами. Использование адаптивного масштабируемого сжатия текстур (ASTC) , мобильного стандарта, обеспечивает превосходное качество изображения по сравнению с ETC2 при том же размере, или позволяет достичь более высоких коэффициентов сжатия при меньшем потреблении памяти при том же целевом качестве изображения.
Оптимизация потоковой передачи текстур
В мобильных средах использование размера пула потоковой передачи текстур Unreal Engine по умолчанию может привести к предварительному выделению чрезмерно большого объема памяти по сравнению со спецификациями устройства. Поэтому идеально определить профили мобильных устройств и выбрать подходящий размер пула потоковой передачи текстур в соответствии с ограничениями памяти устройства. Кроме того, используйте функцию статистики редактора, чтобы проверить статистику текстур и выявить текстуры, потребляющие много памяти и занимающие экстремальные разрешения во время выполнения. Сочетайте это с функцией требуемого разрешения текстур , чтобы установить ограничения или уменьшить максимальное разрешение для ресурсоемких текстур, контролируя использование ресурсов в пределах выделенного буфера памяти для текстур.