Делаешь RTS или тактику в 2D? Показываю, как реализовать выделение нескольких юнитов рамкой. Весь код ниже — бери и пользуйся.
Суть: зажимаешь ЛКМ, тащишь — рисуется прямоугольник. Отпускаешь — все юниты внутри становятся выбранными.
Что понадобится:
- У всех юнитов должен быть Collider2D (Box, Circle — любой).
- Юниты лежат на слое
Units (так проще фильтровать).- На сцене есть камера с тегом MainCamera.
Код менеджера выделения (вешаем на пустой объект):
using UnityEngine;
public class SelectionManager : MonoBehaviour
{
[SerializeField] private LayerMask unitLayerMask; // Слой юнитов в инспекторе
private Vector2 startMousePos;
private bool isDragging = false;
private Rect selectionRect;
void Update()
{
// Начало выделения
if (Input.GetMouseButtonDown(0))
{
startMousePos = Input.mousePosition;
isDragging = true;
}
// Завершение выделения
if (Input.GetMouseButtonUp(0) && isDragging)
{
isDragging = false;
SelectUnitsInRect();
}
// Обновление рамки (для отрисовки)
if (isDragging)
{
UpdateSelectionRect();
}
}
void UpdateSelectionRect()
{
Vector2 currentMousePos = Input.mousePosition;
selectionRect = new Rect(
Mathf.Min(startMousePos.x, currentMousePos.x),
Mathf.Min(startMousePos.y, currentMousePos.y),
Mathf.Abs(startMousePos.x - currentMousePos.x),
Mathf.Abs(startMousePos.y - currentMousePos.y)
);
}
void SelectUnitsInRect()
{
// Конвертируем экранные координаты в мировые
Vector2 min = Camera.main.ScreenToWorldPoint(selectionRect.min);
Vector2 max = Camera.main.ScreenToWorldPoint(selectionRect.max);
// Ищем все коллайдеры внутри прямоугольника
Collider2D[] hits = Physics2D.OverlapAreaAll(min, max, unitLayerMask);
// Сначала снимаем выделение со всех
DeselectAllUnits();
// Выделяем найденных
foreach (var hit in hits)
{
if (hit.TryGetComponent<Unit>(out var unit))
{
unit.SetSelected(true);
}
}
}
void DeselectAllUnits()
{
// Можно найти всех юнитов по тегу или держать список
// Для простоты — ищем все объекты с компонентом Unit
Unit[] allUnits = FindObjectsOfType<Unit>();
foreach (var unit in allUnits)
{
unit.SetSelected(false);
}
}
// Визуализация рамки в редакторе (для отладки)
void OnGUI()
{
if (isDragging)
{
// Конвертируем экранный rect в GUI-координаты
Rect guiRect = new Rect(
selectionRect.x,
Screen.height - selectionRect.y - selectionRect.height,
selectionRect.width,
selectionRect.height
);
GUI.Box(guiRect, "");
}
}
}
Компонент Unit (вешаем на каждого юнита):
using UnityEngine;
public class Unit : MonoBehaviour
{
[SerializeField] private GameObject selectionVisual; // например, спрайт кружка под юнитом
public void SetSelected(bool selected)
{
if (selectionVisual != null)
selectionVisual.SetActive(selected);
}
}
Лайфхак:
- Не забудь в инспекторе у
SelectionManager выставить слой Units в поле unitLayerMask.- Чтобы рамка рисовалась красиво, используй не
GUI.Box, а натяни на Canvas обычный Image и двигай его размеры. Но для старта хватит и этого.-
FindObjectsOfType в DeselectAllUnits — не самый производительный вариант. Для продакшена лучше держать список всех юнитов в менеджере и обновлять его при спавне/смерти.✅ Готово. Теперь зажимай мышку и выделяй армию!
Хочешь такое же передвижение камеры с помощью курсора? Тогда читай этот пост!
🔔 Подпишись, чтобы видеть новые гайды!
👉 Akrus Games | Unity