Клас Enemy
Прописані using System.Collections.Generic;, але не використовуються. Краще його прибрати.
Публічні змінні краще не використовувати. Якщо необхідно задавати значення в редакторі, то можна поставити атрибут [SerializeField]. Використання та зміну значень публічних змінних у зовнішніх класах складно контролювати.
Клас GameController
В коді є багато переведення типів з GameSymbol в int. Краще так не робити. Використання одного типу для індексів та значень є більш прозорим варіантом.
Публічні статичні функції мають бути тільки утилітними. Основна логіка на публічних статичних функціях можу бути зламана зовні.
Клас GameOverController
Перевірка значень через item.image.sprite є не дуже коректною, так як інтерфейсні дані використовуються у якості зберігача інформацій і якщо будуть посилання на одну 1 ту ж картинку, або кртинки не буде зовсім - логіка буде зламана.
Клас Enemy Прописані using System.Collections.Generic;, але не використовуються. Краще його прибрати. Публічні змінні краще не використовувати. Якщо необхідно задавати значення в редакторі, то можна поставити атрибут [SerializeField]. Використання та зміну значень публічних змінних у зовнішніх класах складно контролювати.
Клас GameController В коді є багато переведення типів з GameSymbol в int. Краще так не робити. Використання одного типу для індексів та значень є більш прозорим варіантом. Публічні статичні функції мають бути тільки утилітними. Основна логіка на публічних статичних функціях можу бути зламана зовні.
Клас GameOverController Перевірка значень через item.image.sprite є не дуже коректною, так як інтерфейсні дані використовуються у якості зберігача інформацій і якщо будуть посилання на одну 1 ту ж картинку, або кртинки не буде зовсім - логіка буде зламана.
Строки if (counterActiveButtons == 0) { return true; } else { return false; }
можна замінити на return counterActiveButtons == 0; Логіка не зміниться, а коду значно меньше.
В цілому гарно зроблено!