TGViewer
Unity Tech Дед: Борис Романчиков Unity Tech Дед: Борис Романчиков @unitytechded · 338 subscribers
Post #21 384
🛠️ Удобный способ работы с коллекциями через Builder

Представьте, что вы разрабатываете игру, где есть много врагов, например, survival.io. И есть юнит, который должен атаковать ближайшего юнита ближнего боя.

Как бы выглядел поиск этого юнита в классической реализации


private Enemy GetEnemyClassic()
{
var size = Physics2D.OverlapCircleNonAlloc(center.position, radius, results, layerMask);

for (var i = 0; i < size; i++)
{
var enemy = results[i].GetComponent<Enemy>();

if (enemy.IsDead)
continue;

if (enemy.EnemyType != EnemyType.Melee)
continue;

return enemy;
}

return default;
}


⚠️ Минусы:

* Использование коллайдеров для Physics2D.OverlapCircleNonAlloc.
* Необходимость добавлять специальный слой на врагов (и не забывать добавлять его новым врагам).
* Дорогой вызов GetComponent<Enemy>.
* Сложность восприятия метода при чтении кода.


⚙️ Альтернативный вариант: коллекция + Builder

Я часто использую подход через коллекцию и паттерн Builder.


private Enemy GetEnemyViaBuilder() =>
enemyCollection
.InRadius(center.position, radius)
.IsAlive()
.Melee()
.FirstOrDefault();


✅ Преимущества:

* Упрощение кода и повышение читаемости.
* Отсутствие необходимости работать с коллайдерами и слоями.
* Избавление от вызова GetComponent.

⚠️ Минусы:

* Увеличение времени разработки: требуется написать систему фильтрации и поддерживать коллекцию в актуальном состоянии.

✍️ Пример реализации коллекции


public class EnemyCollection
{
private readonly FilterData filter = new();
private IEnumerable<Enemy> enemies;

public EnemyCollection(IEnumerable<Enemy> enemies)
{
this.enemies = enemies;
}

public EnemyCollection IsDead()
{
filter.IsDead = true;
return this;
}

public EnemyCollection IsAlive()
{
filter.IsDead = false;
return this;
}

public EnemyCollection Melee()
{
filter.EnemyType = EnemyType.Melee;
return this;
}

public EnemyCollection InRadius(Vector3 center, float radius)
{
filter.InFilterByRadius = true;
filter.Center = center;
filter.Radius = radius;
return this;
}

public Enemy FirstOrDefault()
{
return Build().FirstOrDefault();
}

public IEnumerable<Enemy> Build()
{
if (filter.IsDead.HasValue)
{
enemies = enemies.Where(e => e.IsDead == filter.IsDead);
}

if (filter.EnemyType.HasValue)
{
enemies = enemies.Where(e => e.EnemyType == filter.EnemyType);
}

if (filter.InFilterByRadius)
{
enemies = enemies.Where(e => Vector3.Distance(filter.Center, e.transform.position);
}

filter.Clear();
return enemies;

}

private class FilterData
{
public bool? IsDead;
public EnemyType? EnemyType;
public bool InFilterByRadius;
public float Radius;
public Vector3 Center;

public void Clear()
{
IsDead = null;
EnemyType = null;
InFilterByRadius = false;
Radius = 0;
Center = new Vector3();
}
}
}


Код, приведеный выше служит лишь примером, что бы передать главнную мысль об использовании кастомных коллекций в связке с Builder. В реальных проектах такие коллекции могут иметь альтернативные реализации, содержать различные кеши для ускорения поиска или фильтрации и многие другие "удобные".

Напишите в комментариях ваше мнение о таком решении! 🚀
  • 🔥 4
  • ❤ 2
  • 👌 2
More from @unitytechded
  1. Sep 25, 2026🛠 Как Astra меняет мой подход к разработке В последнее время много экспериментировал с As…
  2. Aug 30, 2026Bioneers Closed Demo — финальные результаты первых 48 часов Подвели итоги первых 48 часов…
  3. Aug 28, 2026Bioneers вышел в закрытое тестирование! Ровно год назад началась разработка игры, а сегодн…
  4. Jun 10, 2026Почему никто не использует Test-Driven Development в геймдеве? Разбирал тут наши старые до…
  5. May 18, 2026Как оформить CV разработчику. Часть 2 Если коммерческого опыта мало, можно указать pet-про…
  6. May 18, 2026Как оформить CV разработчику. Часть 1 Хочу начать с важной ремарки: я не профессиональный…
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 →