Привет, Хабр!

Это моя первая статья, поэтому для начала представлюсь. Меня зовут Виктор, мне 40 лет, из которых почти 20 я на разных ролях участвую в разработке различного программного обеспечения для крупных корпораций (в основном финтех). Путь был долгий и тернистый, но сейчас я занимаю роль Системного архитектора и по совместительству Руководителя направления интеграции.

Я всегда любил игры, у меня даже был собственный канал с летсплеями и обзорами разных игр, который, к сожалению, не сыскал успеха. Несмотря на это, около двух лет назад я решил с ноги ворваться в мир геймдева. Ничто не предвещало беды, просто одним февральским вечером будто щелкнуло что-то в мозгу - ХОЧУ… ДЕЛАТЬ… ИГРЫ…

Я человек самодостаточный, так что если хочу, значит, делаю. И на самом деле это очень интересное ощущение - в 40 лет почувствовать себя беспробудным джуном в той области, в которой совершенно ничего не понимаешь, но тебе так интересно.

С чего начать? Паника первого шага

Первые недели были похожи на блуждание в тумане. В корпоративном мире у меня есть имя, репутация, я понимаю каждый процесс и знаю, к какому специалисту обратиться с любым вопросом. Здесь же я был чистым листом.

Мой внутренний архитектор сразу же попытался выстроить «стратегию»:

Выбор движка. Начал с банального гугления «какой движок выбрать для новичка». Unity vs Unreal Engine - это холивар, который для новичка звучит как спор о преимуществах космических кораблей, когда ты не умеешь водить машину. После недели изучения остановился на Unity. Я хорошо знаком с Java, они с C# как братья близнецы, а вот “плюсы” в моей жизни были слишком давно. Плюс, сообщество казалось более дружелюбным к инди-разработчикам.

Первый “Hello, World!”... который в геймдеве превращается в “Hello, Cube!”. Помню этот детский восторг, когда я заставил красный куб вращаться по нажатию кнопки. Это было волшебство. Но эйфория быстро сменилась осознанием: между вращающимся кубом и даже самой простой игрой - пропасть.

От корпоративной Java к Unity API

Знание Java из enterprise (и, соответственно “Узнавание C#”) не подготовило меня к работе с Unity API. В корпоративной Java ты работаешь с классами, коллекциями, базами данных. В Unity - с GameObject, Transform, Rigidbody, Collider.

Конкретный пример: "Простейшая задача - заставить объект двигаться”. Вместо привычного цикла или таймера, я столкнулся с Update() и FixedUpdate(). Понятие Time.deltaTime для независимости от частоты кадров стало небольшим открытием. Вот мой первый “движок” для куба:

public class SimpleMover : MonoBehaviour
{
    public float speed = 5.0f;
    void Update()
    {
        //Вначале я делал так:
        // transform.position += new Vector3(speed, 0, 0);
        
        // Но потом прочитал документацию:
        float movement = speed * Time.deltaTime;
        transform.Translate(movement, 0, 0);
    }
}

Стена: когда 20 лет опыта мешают

Самым неожиданным для меня стало то, как мой богатый опыт в enterprise-разработке мешал мне.

Перфекционизм vs Прототипирование. В финтехе любая строчка кода - это потенциальные миллионы убытков или риски для безопасности. Все должно быть идеально: архитектура, паттерны, документация. В геймдеве на ранних этапах главное - скорость итераций. “Сделал работающий прототип? Отлично! Выкидывай и делай заново, но уже с новыми знаниями”. Мой внутренний архитектор плакал, когда я видел свой “говнокод”, но играющий прототип уровня “собери 10 монеток” приносил несоизмеримо больше пользы.

Архитектурная битва: MonoBehaviour vs Чистый C#

Мой перфекционизм архитектора требовал создать абстракции для всего. Я пытался делать GameEntity, ICharacterController и инжектить зависимости, но сталкивался с тем, что MonoBehaviour не любит сложных конструкторов и живет в своем собственном жизненном цикле.

Конкретный пример: я потратил день, пытаясь заставить систему управления состоянием персонажа работать через интерфейсы. В итоге, для прототипа оказалось достаточно простого конечного автомата прямо внутри MonoBehaviour:

public class SimplePlayerController : MonoBehaviour
{
    public enum PlayerState { Idle, Running, Jumping }
    public PlayerState CurrentState { get; private set; }
    
    void Update()
    {
        switch (CurrentState)
        {
            case PlayerState.Idle:
                if (Input.GetKey(
KeyCode.Space)) CurrentState = PlayerState.Jumping;
                break;
            case PlayerState.Jumping:
                // Логика прыжка...
                break;
        }
    }
}

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

Сложное vs Простое. Мой мозг сразу же начинал выстраивать сложные абстракции и системы данных для игры-платформера. А нужно было просто заставить персонажа прыгать и не падать сквозь пол. Я потратил три дня на проектирование “масштабируемой системы управления игровыми сущностями”, вместо того чтобы просто сделать десять платформ.

Проблема коллизий: 2D vs 3D физика

Конкретный пример. Создавая свою первую 2D-игру, я по привычке использовал Rigidbody (который по умолчанию 3D) и долго не мог понять, почему коллизии не работают. Оказалось, для 2D нужен Rigidbody2D и коллайдеры BoxCollider2D. Это кажется очевидным, но для новичка - час-два гугления. Понимание разницы между OnCollisionEnter и OnTriggerEnter было еще одним ключевым моментом.

Синдром самозванца... наоборот. В корпорации я - эксперт. Здесь я - ноль. Было непривычно и даже унизительно смотреть 40-минутные туториалы на YouTube, чтобы понять, как работает Rigidbody. Приходилось заново учиться быть учеником: не бояться задавать глупые вопросы на форумах, признаваться в незнании и принимать критику.

Что же помогло? Три столпа выживания

Несмотря на все трудности, я не сдался. Мне помогли три вещи, которые я вынес из своего “прошлого” опыта.

Дисциплина. Я не ждал вдохновения. Я выделил под геймдев ровно 10 часов в неделю (два вечера по будням и одно воскресное утро) и жестко их придерживался. Это был мой “технический долг” перед самим собой.

Умение учиться. За 20 лет в IT я сменил с десяток технологий. Я давно понял, что главный навык - не знание конкретного фреймворка, а умение находить и усваивать информацию. Этот навык оказался бесценным.

Сообщество. Я нашел локальное сообщество инди-разработчиков. Видеть, как другие, такие же энтузиасты, сталкиваются с теми же проблемами, что и ты, и вместе искать решения - это невероятно мотивирует. В корпоративном мире ты часто варишься в собственном соку, а здесь - чувствуешь себя частью чего-то живого и творческого.

Технические инсайты: что я вынес спустя два года

Вот несколько конкретных технических уроков, которые могут быть полезны другим новичкам:

1. ScriptableObjects — лучший друг архитектора

Эти объекты стали для меня открытием. Я использую их для хранения данных о врагах, настройках оружия, конфигурации уровней. Это чистейшие данные, которые не привязаны к сцене, и их можно менять в рантайме, что идеально ложится на мой опыт работы с конфигами в enterprise.

[CreateAssetMenu(fileName = "WeaponData", menuName = "Game/Weapon Data")]
public class WeaponData : ScriptableObject
{
    public string weaponName;
    public float damage;
    public float fireRate;
    public GameObject projectilePrefab;
}

2. Оптимизация Draw Calls

Когда количество объектов на сцене перевалило за тысячу, игра начала тормозить. Статический батчинг и использование Атласов для спрайтов решили проблему. Я научился пользоваться Профайлером и Frame Debugger — инструментами, без которых в геймдеве никуда.

3. Работа с Asset Bundles и Addressable Assets

Для моей текущей комплексной игры стало ясно, что ресурсы нужно подгружать динамически. Изучение этой системы изменило мой подход к организации контента. Вместо ручного перетаскивания ассетов на сцену, я теперь думаю о том, как они будут загружаться в память и выгружаться из нее.

public class AssetLoader : MonoBehaviour
{
    public async Task<GameObject> LoadAssetAsync(string address)
    {
        var handle = Addressables.LoadAssetAsync<GameObject>(address);
        await handle.Task;
        return handle.Result;
    }
}

И что в итоге?

Прошло почти два года. Я не создал новый “Ведьмак” и даже не разбогател. Но я сделал несколько джем-игр, пару небольших, но законченных казуалок для мобилок. А сейчас я полностью погружен в разработку своего первого комплексного проекта. Это амбициозно, сложно и невероятно увлекательно.

Это по-прежнему хобби, которое отнимает все свободное время, которого и так немного, но оно того стоит.

Так что же я получил, сменив уютное кресло архитектора на нелегкий путь джуна в геймдеве?

Оживление ума. Изучение совершенно новой области встряхнуло мой мозг так, как никакие корпоративные тренинги не могли. Я снова почувствовал азарт первооткрывателя.

Новое видение своей основной работы. Невероятно, но эти “игрушки” сделали меня лучше в моей основной работе. Я стал проще относиться к прототипам, чаще применять подход “сделай-проверь-переделай” и ценить быстрые итерации.

Чистое творчество. В корпоративном мире твой успех измеряется в KPI, ROI и выполненных спринтах. В геймдеве (на моем уровне) успех - это момент, когда твой друг смеется от придуманной тобой глупой механики или когда ты сам ��олучаешь удовольствие от геймплея, который создал. Это невероятно заряжает.

Резюме для тех, кто думает так же

Если вам за 30, 40, 50, и у вас в голове зажегся тот самый “огонек” - не гасите его. Неважно, геймдев это, керамика или Data Science.

Ваш опыт - не якорь, а балласт, который поможет вам не сбиться с курса. Вы уже умеете учиться, планировать и доводить дело до конца. Вам будет сложно, некомфортно и временами стыдно за свои “детские” ошибки. Но ощущение, когда ты преодолеваешь очередную “стену” и видишь результат своего труда - бесценно.

Это не призыв бросить работу и ринуться в омут. Это напоминание, что можно быть серьезным архитектором днем и безумным джуном-геймдевом по вечерам. И в этом безумии есть своя гармония.

А у вас был подобный опыт? Пробовали ли вы кардинально сменить фокус в зрелом возрасте? Делитесь в комментариях!