TGViewer
Game Development | YeaHub Game Development | YeaHub @yeahub_game_dev · 370 subscribers
Post #394 249
🧹 Сборщик мусора в Unity - как оптимизировать?

Продолжаем тему оптимизаций и сегодня поговорим о сборщике мусора.

Сборщик мусора (GC) - это система, которая освобождает память, когда объект больше не используется.
Проблема в том, что во время сборки мусора игра фризится - GC останавливает всё, чтобы убрать неиспользуемые объекты.
Поэтому, ваша цель - уменьшить количество мусора и управлять сборкой вручную, когда это безопасно.

1️⃣ Включите инкрементальный GC

Unity поддерживает Incremental GC. В таком случае сборка мусора выполняется не целиком, а частями - по кадрам.
Так фризы становятся почти незаметными.
Включается в Project Settings → Player → Other Settings → Configuration → Incremental GC.

2️⃣ Собирайте мусор вручную в удобные моменты

Вместо того, чтобы GC отрабатывал в важные моменты геймплея - можно самому вызвать сборку в визуально простые моменты игры, где фризы экрана будут незаметны.
Обычно это экраны пауз - часто они статичные, или имеют простую анимацию.

Вызов сборки мусора:
GC.Collect();


3️⃣ Не используйте конкатенацию строк в циклах или Update

Каждая конкатенация строки == новый объект и мусор для сборки. Если цикл состоит из 16 итераций - будет создано 16 строк, что окажет большую нагрузку на GC.

Плохо:
string ConcatExample(string[] stringArray) {
string result = "";

for (int i = 0; i < stringArray.Length; i++) {
result += stringArray[i]; // каждый раз - новый объект
}

return result;
}


Хорошо:
private StringBuilder _sb = new StringBuilder(16);

string ConcatExample(string[] stringArray) {
_sb.Clear();

for (int i = 0; i < stringArray.Length; i++) {
_sb.Append(stringArray[i]); // используем StringBuilder - так создадим только один объект строки
}

return _sb.ToString();
}


4️⃣ Кешируйте строки

Типичная ошибка - обновление текста при любом обновлении счётчика или постоянно в Update.
Кешируйте текст и обновляйте только при изменении значения.

Плохо:
    public Text scoreBoard;
public int score;

void Update() {
string scoreText = "Score: " + score.ToString(); // создаём новый объект каждый кадр
scoreBoard.text = scoreText;
}


Хорошо:
    public Text scoreBoard;
public string scoreText;
public int score;
public int oldScore;

void Update() {
if (score != oldScore) {
scoreText = "Score: " + score.ToString(); // создаём новые объект, только если значение изменилось
scoreBoard.text = scoreText;
oldScore = score;
}
}


5️⃣ Используйте NonAlloc-версии методов

Многие API в Unity создают мусор: Physics.OverlapSphere, Physics.Raycast и т.д.

Иногда есть версии с суффиксом NonAlloc:
Physics.OverlapSphereNonAlloc(position, radius, colliders);


При написании своих методов - следуйте той же идее: не создавайте новые массивы, если можно переиспользовать старые.

💡 Вывод и дополнительные материалы

Оптимизация GC - это не сложно.
Главное - избегать лишних аллокаций и управлять сборкой в удобные моменты.
Чем меньше мусора вы создаёте, тем плавнее идёт игра.

Статья от Unity по оптимизации GC
Профайлинг GC от GameDevGuru

🚀 Пост Guru Unity: @Minerope
  • ❤ 1
  • 👍 1
  • 🐳 1
More from @yeahub_game_dev
  1. Oct 9, 2026#video #unity 📚 FREE Complete Unity Game Development Courses Полный бесплатный курс по ра…
  2. Oct 8, 2026#Собес #lost #update 🤔 Что такое lost update и при каких условиях он возникает? 💬 Кратко…
  3. Oct 7, 2026#Собес #Task #ThreadPool #async 🤔 Как Task использует ThreadPool? 💬 Кратко: Task использ…
  4. Oct 5, 2026#Собес #memory_layout #data_alignment #padding 🤔 Какие есть исключения из правил хранения…
  5. Oct 2, 2026#tool #гит 📚 Хочешь изучить Git, не рискуя своей локальной установкой? Теперь можно запус…
  6. Oct 1, 2026#Собес #docker_rm #container #stop 🤔 Как удалить Docker-контейнер? 💬 Кратко: Чтобы удали…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →