
Unity – это не один язык, а связка технологий, каждая из которых отвечает за свою часть движка. Ядро Unity реализовано на C++: на нём написаны системы рендеринга, физики, работы с памятью, сцены и платформенные абстракции. Именно C++ обеспечивает высокую производительность и возможность сборки под Windows, macOS, Linux, Android, iOS и консоли.
Для разработки логики игр и приложений используется C#. Все пользовательские скрипты в Unity пишутся на C# и работают поверх одного из двух рантаймов: Mono или IL2CPP. Mono применяется в редакторе и при отладке, а IL2CPP конвертирует C#-код в C++ с последующей компиляцией, что используется при сборке под мобильные устройства и консоли.
Отдельный слой составляют языки шейдеров. Для графики Unity применяет HLSL, который затем автоматически транслируется под нужный графический API: DirectX, Vulkan, Metal или OpenGL. Это означает, что визуальные эффекты, освещение и постобработка фактически пишутся не на C#, а на специализированном языке для GPU.
Ранее Unity поддерживал UnityScript и Boo, но они полностью удалены. При выборе стека для работы с движком на практике имеет смысл сосредоточиться на C# для геймплейной логики и на HLSL для графики, а понимание C++ полезно при работе с нативными плагинами и анализе производительности.
Язык C++ в ядре Unity и движке рендеринга

Рендеринг в Unity опирается на C++ для взаимодействия с графическими API: DirectX (Windows), Vulkan (Android/PC), Metal (iOS/macOS), OpenGL (устаревшие конфигурации). Нативный слой управляет командными буферами, синхронизацией, загрузкой ресурсов и шейдерными пайплайнами, что критично для стабильного FPS и предсказуемых задержек.
Современные рендер-пайплайны Unity (URP и HDRP) используют C++ для базовой инфраструктуры рендера: сортировки и батчинга, управления состояниями GPU, асинхронной загрузки текстур и мешей. Логика пайплайнов на стороне C# лишь конфигурирует и оркестрирует нативные вызовы, не подменяя их.
Связка управляемого и нативного кода обеспечивается через IL2CPP: C#-скрипты конвертируются в C++ и компилируются в нативные бинарники. Это уменьшает расходы рантайма, повышает совместимость с мобильными и консольными платформами и упрощает отладку проблем, связанных с производительностью.
Практические рекомендации: прибегать к C++ через Native Plugins только для задач с жёсткими требованиями по задержкам (кодеки, физика, кастомные алгоритмы обработки данных). Для графики следует использовать предоставленные API рендера и избегать прямых вызовов GPU вне нативного слоя Unity, чтобы не нарушать синхронизацию и кроссплатформенность.
Роль C# при создании игровых скриптов и логики

Через C# реализуется управление жизненным циклом объектов с помощью методов Awake, Start, Update, FixedUpdate и LateUpdate. Эти точки входа напрямую связаны с внутренним циклом движка и позволяют точно контролировать инициализацию, физику, ввод пользователя и визуальные обновления. Для физики используются FixedUpdate и API PhysX, для логики интерфейса – события UI и система EventSystem.
C# применяется для работы с системой ввода (Input System), анимацией (Animator Controller, StateMachineBehaviour), звуком (AudioSource, AudioMixer), сценами и адресуемыми ресурсами (Addressables). Вся логика загрузки, выгрузки и управления памятью на уровне проекта пишется на C#, при этом низкоуровневые операции выполняются нативной частью Unity.
Для повышения производительности активно используются структуры данных из Unity.Collections, а также компилятор Burst и Job System. C#-код, написанный с учетом требований Burst (без managed-объектов и виртуальных вызовов), компилируется в оптимизированный машинный код и применяется в задачах, чувствительных к скорости: ИИ, симуляции, массовые вычисления.
C# также определяет инструментарий редактора: кастомные инспекторы, окна редактора, меню и автоматизация сборок создаются через UnityEditor API. Это позволяет адаптировать рабочий процесс под конкретный проект и сократить время разработки без изменения ядра движка.
Рекомендация при работе с C# в Unity – строго разделять игровую логику, данные и представление. Использование ScriptableObject для конфигураций, событийных моделей вместо прямых ссылок и отказ от логики в Update без необходимости напрямую влияет на читаемость кода и стабильность проекта.
Использование IL2CPP при сборке проектов под разные платформы

При использовании IL2CPP сборка проекта проходит несколько этапов: анализ сборок C#, генерация эквивалентного C++-кода, компиляция через нативный компилятор платформы и линковка в итоговый бинарный файл. В результате игра запускается без среды .NET и не требует Mono во время выполнения.
IL2CPP обязателен для платформ iOS, tvOS, PlayStation, Xbox, Nintendo Switch, а также часто используется при сборке под Android и WebGL. Для Windows, macOS и Linux разработчик может выбирать между Mono и IL2CPP, ориентируясь на требования проекта.
С точки зрения производительности IL2CPP даёт более предсказуемое время выполнения: отсутствуют паузы JIT-компиляции, упрощается работа сборщика мусора, снижается количество аллокаций при корректной настройке. Это особенно заметно на мобильных устройствах и консолях с ограниченными ресурсами.
Отладка проектов с IL2CPP требует отдельного подхода. Стек вызовов сложнее интерпретировать, а горячая перезагрузка кода недоступна. Рекомендуется активно использовать Development Build, логирование, символы отладки и профилировщик Unity до перехода на финальные сборки.
При работе с IL2CPP следует учитывать ограничения: недоступна генерация кода во время выполнения, рефлексия работает только для явно используемых типов, а обфускация может влиять на корректность сборки. Для сохранения необходимых классов и методов применяется файл link.xml, который предотвращает их удаление на этапе оптимизации.
Практическая рекомендация: подключать IL2CPP на раннем этапе, если целевая платформа его требует. Это позволяет выявить несовместимые библиотеки, проблемы с сериализацией и рефлексией до роста кодовой базы и снижает риски при финальной сборке.
Где применяются C и C++ в нативных модулях и плагинах Unity

C и C++ используются в Unity там, где требуется прямой доступ к нативным API платформы, минимальные задержки и полный контроль над памятью. Основная область – разработка нативных плагинов, подключаемых к проектам на C# через P/Invoke или Unity Native Plugin Interface. Такой подход применяется для расширения возможностей движка без модификации его исходного кода.
На мобильных платформах C и C++ применяются для интеграции Android NDK и iOS SDK. Через нативные плагины реализуется работа с камерой, датчиками, Bluetooth, NFC, биометрией, нестандартными аудиоустройствами и системными сервисами, которые недоступны напрямую из C#. Для iOS чаще используется Objective-C++ с C++-ядром, для Android – C++ с JNI-обвязкой.
В высоконагруженных вычислениях C++ используется для физики, обработки геометрии, навигационных сеток, процедурной генерации и пользовательских алгоритмов, чувствительных к задержкам. Это актуально для симуляторов, VR/AR и проектов с большим количеством объектов, где управляемая среда C# становится узким местом по производительности или потреблению памяти.
Графические плагины на C++ позволяют внедрять собственные этапы рендеринга: постобработку, нестандартные буферы, работу с Compute Shader через нативные API DirectX, Vulkan и Metal. Такие плагины используются для кастомных эффектов, видеостриминга, захвата изображения с GPU и интеграции сторонних рендер-систем.
Сторонние SDK чаще всего предоставляются именно в виде библиотек на C или C++. Примеры – системы аналитики, античита, голосовой связи, рекламные и платежные модули, компьютерное зрение и машинное обучение. Unity выступает в роли оболочки, а основная логика выполняется в нативном коде, что упрощает кросс-платформенную поддержку и обновление SDK.
При разработке собственных нативных плагинов рекомендуется выносить в C++ только узкие, ресурсоёмкие участки, оставляя управление сценами и логикой в C#. Интерфейс плагина должен быть минимальным: простые типы данных, явное управление жизненным циклом и отсутствие исключений на границе managed/unmanaged. Это снижает накладные расходы и упрощает отладку на разных платформах.
Языки шейдеров: HLSL и ShaderLab в графической части Unity

Графическая подсистема Unity опирается на связку ShaderLab и HLSL. ShaderLab выступает декларативной оболочкой, описывающей структуру шейдера, параметры материалов, наборы проходов и правила их применения в разных режимах рендеринга. HLSL используется внутри этих проходов для реализации вычислений вершин, фрагментов, теней и дополнительных стадий конвейера.
ShaderLab определяет блоки Properties, SubShader и Pass, что позволяет на уровне движка управлять совместимостью с платформами, качеством рендеринга и очередностью отрисовки. Например, несколько SubShader в одном файле дают возможность задать альтернативные реализации для мобильных GPU и настольных видеокарт без дублирования логики материалов.
HLSL в Unity применяется в диалекте, адаптированном под кроссплатформенную компиляцию. Исходный код транслируется в SPIR-V, Metal Shading Language или GLSL в зависимости от целевой платформы. Это снимает необходимость писать разные версии шейдеров для DirectX, Vulkan и Metal, но накладывает ограничения на используемые конструкции и версии языка.
Для встроенных пайплайнов (Built-in Render Pipeline) и URP используется классическая модель вершинных и фрагментных шейдеров. В HDRP активно задействуются дополнительные стадии, включая compute-шейдеры для постобработки, освещения и работы с буферами. Compute-шейдеры также пишутся на HLSL и позволяют выполнять параллельные вычисления вне стандартного графического прохода.
При разработке рекомендуется выносить математическую логику в отдельные HLSL-файлы и подключать их через директивы include. Это упрощает поддержку кода и снижает риск расхождений между разными шейдерами. Для параметров, доступных из C#, следует использовать чёткие соглашения по именованию и типам данных, чтобы избежать лишних преобразований на стороне движка.
| Компонент | Назначение | Практическое применение |
|---|---|---|
| ShaderLab | Описание структуры и правил рендеринга | Настройка очередей отрисовки, тегов, вариантов качества |
| HLSL | Вычисления на GPU | Вершинные, фрагментные и compute-шейдеры |
| Compute Shader | Параллельные вычисления без геометрии | Постобработка, симуляции, работа с текстурами и буферами |
Для стабильной работы на разных платформах следует проверять шейдеры через Shader Variant Collection и анализировать отчёты компиляции. Это позволяет заранее выявить неподдерживаемые инструкции и сократить количество вариантов, загружаемых в память во время выполнения.
Почему Unity отказался от UnityScript и Boo

UnityScript (вариант JavaScript с типизацией) и Boo (язык на базе Python с поддержкой .NET) использовались в Unity до версии 2017. Их поддержка была полностью прекращена, а C# остался единственным языком для пользовательских скриптов.
Ключевая причина – техническая сложность поддержки нескольких языков поверх одного API. Каждое изменение движка требовало синхронных обновлений документации, примеров, компилятора и отладочных инструментов для всех языков, что замедляло развитие редактора и рантайма.
- Разные языки – разные компиляторы и пайплайны сборки, что усложняло внедрение IL2CPP и оптимизаций под мобильные и консольные платформы.
- UnityScript и Boo имели ограниченную поддержку современных возможностей .NET и Mono по сравнению с C#.
- Меньшее сообщество пользователей этих языков приводило к дефициту библиотек, примеров и сторонних инструментов.
Отдельной проблемой стала экосистема. Большинство ассетов в Asset Store, официальных SDK и интеграций (Ads, Analytics, IAP, XR) ориентировались исключительно на C#. Поддержка UnityScript и Boo фактически означала дублирование кода и тестирования.
- Документация и обучающие материалы в основном публиковались для C#.
- Инструменты IDE (Visual Studio, Rider) имели лучшую интеграцию именно с C#.
- Асинхронные паттерны, LINQ и строгая типизация были доступны и стабильно работали только в C#.
С точки зрения производительности и сопровождения C# оказался более предсказуемым. Он напрямую компилируется в IL, корректно обрабатывается IL2CPP и позволяет применять единый набор оптимизаций без языковых исключений.
Практический результат отказа от UnityScript и Boo:
- Снижение сложности движка и ускорение выпуска новых версий.
- Единый API без языковых расхождений и скрытых ограничений.
- Фокус на развитии C# как основного инструмента для логики, редакторских расширений и runtime-кода.
Рекомендация для существующих проектов: при миграции со старых версий Unity переводить UnityScript и Boo на C# с одновременной проверкой работы под IL2CPP, так как автоматическая конвертация не учитывает различия в типизации, областях видимости и обработке событий.
Вопрос-ответ:
На каких языках написано ядро Unity?
Основная часть движка Unity реализована на C++. Этот язык используется для работы с рендерингом, физикой, обработкой ввода и другими низкоуровневыми компонентами, требующими высокой производительности. C++ обеспечивает прямой контроль над памятью и системными ресурсами, что важно для кроссплатформенного движка.
Почему в Unity используется C# для написания скриптов?
C# выбран для создания игровой логики и взаимодействия с API Unity. Этот язык сочетает удобство высокого уровня с управляемым выполнением кода, что облегчает разработку и снижает количество ошибок. Скрипты на C# компилируются в промежуточный код, который затем может выполняться с помощью CLR или преобразовываться в нативный код через IL2CPP для разных платформ.
Что такое IL2CPP и зачем он нужен?
IL2CPP — это технология, которая преобразует промежуточный код C# в C++, а затем компилирует его в нативный машинный код под целевую платформу. Это увеличивает скорость выполнения, сокращает нагрузку на сборщик мусора и обеспечивает совместимость с платформами, где стандартная виртуальная машина .NET недоступна.
Какие языки используются для написания шейдеров в Unity?
Для создания графики и визуальных эффектов Unity применяет HLSL и ShaderLab. HLSL позволяет писать низкоуровневые шейдерные программы, контролирующие освещение, текстуры и материалы. ShaderLab служит для структурирования шейдеров, их параметров и интеграции с редактором Unity.
Почему Unity отказался от UnityScript и Boo?
UnityScript (похожий на JavaScript) и Boo перестали поддерживаться из-за низкой востребованности и сложностей с поддержкой компилятора и совместимости с C#. Упор на C# позволил упростить экосистему, ускорить разработку и улучшить интеграцию с инструментами и сторонними библиотеками.
