Глобальная перепись кода — как я пересобрал «Прощай» и что из этого вышло

Следите за анонсами на itch.io

Последние дни я провёл не за написанием новых диалогов и не за рисованием спрайтов, а за тем, что переписал практически весь код игры. Сначала я думал, что можно обойтись точечными правками, но чем дальше, тем больше система давала сбоев: переходы между сценами работали через раз, позиция игрока терялась, меню паузы и дверей конфликтовали, а при сборке билда всё разбегалось кто куда. Пришлось остановиться и пересобрать архитектуру с нуля.

Ниже хроника этой перестройки, трудности, с которыми я столкнулся, и то, как они решались. Надеюсь, мой опыт пригодится тем, кто тоже мучается с Unity.

1. От разрозненных скриптов к единому GameManager

Было:Скрипты сохранения, загрузки, переходов, дней и мета-слоя были раскиданы по разным объектам. Каждый сам решал, когда сохранять позицию, а когда загружать. В результате при переходе из кухни в комнату игрок иногда оказывался за стеной, а день мог сброситься на первый.

Стало:Я ввёл GameManager - синглтон, который живёт между сценами и централизованно управляет переходами (ChangeLocation), днями, позицией игрока. Теперь все переходы идут через него, а сохранения (временные) тоже хранятся в нём.

Трабл:Сначала я намудрил с DontDestroyOnLoad и в итоге получил два GameManager в сцене. Один из них был неактивен, из-за чего корутины не запускались, и двери перестали работать. Пришлось прописать в Awake правильную проверку и удалять дубликаты.

2. Меню паузы и двери: курсор и активность

Было:Меню паузы открывалось по Esc, но курсор не появлялся. А при открытии меню дверей курсор появлялся, но потом его нельзя было спрятать. В итоге игрок мог кликать по UI, не видя мыши.

Стало:Я добавил в PauseMenu и DoorWithMenu явное управление Cursor.visible и Cursor.lockState. При открытии меню курсор виден и свободен, при закрытии скрыт и заблокирован в центре. Также пришлось прописать отключение управления игроком ( player.enabled = false ), чтобы он не ходил, пока висит меню.

Трабл:Сначала я забыл отключать PlayerMovement в меню дверей, и персонаж продолжал двигаться под интерфейсом. Потом наоборот отключал, но не включал обратно при закрытии. Долго ловил эти гонки.

3. Анимации: почему спрайт то появлялся, то исчезал

Это была самая нервная часть. Анимации ходьбы работали, но в некоторых кадрах персонаж исчезал. Я проверил всё: SpriteRenderer, Order in Layer, скрипты. Причина оказалась в анимационном клипе: в нём были пустые кадры и ключи на enabled = false.

Решение:Я заново пересобрал анимации: выделил все кадры в окне Project, перетащил на персонажа - Unity сама создала новый клип. Потом в Animator добавил параметр Speed (Float) и настроил переходы: Idle → Walk при Speed > 0.1, Walk → Idle при Speed < 0.1. Теперь персонаж ходит без пропаданий.

4. Камера в билде: объекты разбегаются

Когда я собрал первый билд после всех правок, ужаснулся: камера показывала только центр сцены, а все объекты сместились. Оказалось, что в билде разрешение экрана отличается от того, что я видел в редакторе.

Решение:Я написал скрипт CameraFitter, который подстраивает ортографический размер камеры под реальное разрешение экрана, сохраняя пропорции заданной игровой области. Теперь в любом окне сцена видна целиком.

5. Настройки: кнопки не привязывались и GameManager выключался

Сначала в инспекторе кнопок настроек и выхода не было методов OpenSettings и QuitGame. Пришлось переписать MainMenu, явно добавив эти методы и убедиться, что объект со скриптом правильно перетаскивается в OnClick.

Потом возникла новая проблема: после закрытия настроек GameManager становился неактивным. Оказалось, что скрипт SettingsManager висел на том же объекте, что и GameManager, и в ClosePanel() вызывался gameObject.SetActive(false). Я вынес SettingsManager на отдельную панель, а в ClosePanel() отключаю только её.

6. Что в итоге

Сейчас код выглядит так:

  • GameManager -- один на все сцены, управляет переходами, днями, позицией игрока.
  • DayCycle -- просто триггер для смены дня (вся логика в GameManager).
  • DoorWithMenu -- вызывает GameManager.ChangeLocation, сам открывает/закрывает меню дверей, управляет курсором.
  • PlayerMovement -- только движение и передача скорости в аниматор.
  • CameraFitter -- адаптация камеры под любой экран.
  • MainMenu -- кнопки и вызов GameManager.StartGame().
  • SettingsManager -- настройки на отдельном объекте, не трогает GameManager.

7. Ошибки, которые я запомнил

  • Нельзя вешать скрипты, которые отключают объект, на критически важные менеджеры.
  • Корутины не запускаются на неактивных объектах. Всегда проверяйте gameObject.activeInHierarchy.
  • Анимации нужно пересобирать, если они сломались, а не искать причину в коде.
  • Ссылки в инспекторе - самое слабое место. После каждой пересборки префабов они слетают, и это нормально, нужно проверять заново.

8. Что дальше

Теперь, когда архитектура стабильна, я возвращаюсь к контенту:

  • Интеграция диалогов (тексты уже написаны).
  • Флешбек (центральная сцена).
  • Звуки шагов, дронов, атмосферы.
3
1
1
11 комментариев