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

Это моя первая статья, поэтому для начала представлюсь. Меня зовут Виктор, мне 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.

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

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

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