Создайте собственный игровой контроллер на Arduino и Unity
О чём эта инструкция
- Сборка простого контроллера: потенциометр + тактовая кнопка на макетной плате.
- Настройка Arduino с прошивкой Firmata для связи с Unity.
- Подключение Unity с помощью плагина Uniduino (встроенный тест-панель).
- Написание скриптов C# для чтения аналогового значения и управления сферой в сцене.
- Добавление спауна падающих кубов и взаимодействий.
Важно: все изображения и схемы из оригинала сохранены. Путь к файлам и URL не изменены.
Требования к проекту
- Arduino Uno или аналогичный микроконтроллер
- 1 × резистор 10 кОм
- 1 × моментальная (тактовая) кнопка
- 1 × потенциометр
- Провода для макетной платы (hook-up wires)
- Макетная плата (breadboard)
- Unity game engine
- Плагин Uniduino из Unity Asset Store (платный ~30$ на момент написания)
- Исходный код проекта (если не хотите писать вручную)
Большинство компонентов доступно в комплекте для изучения Arduino. Вы можете усложнить контроллер любым количеством энкодеров, джойстиков и датчиков — в примере используется только потенциометр и кнопка, что идеально для простого аркадного управления.

ALT: Схема и макетная плата с подключённым Arduino и элементами управления — потенциометр и кнопка.
Сборка контроллера на макетной плате
Соберите схему как на изображении ниже: подключите потенциометр к 5V, GND и аналоговому входу (в примере — A5). Кнопку подключите к цифровому пину (в примере — D2), подтянув к GND через 10 кОм или используя внутренний подтягивающий резистор в настройках. Эта простая сборка также подходит для DIY MIDI-контроллера при небольших изменениях.
ALT: Фото макетной платы с подключённым потенциометром и кнопкой, провода ведут к Arduino Uno.
ALT: Fritzing-диаграмма, показывающая распиновку Arduino и размещение компонентов на макетной плате.
Подготовка Arduino
- Подключите Arduino по USB к компьютеру.
- В Arduino IDE выберите Tools > Board и Tools > Port, укажите вашу плату и COM-порт.
- Откройте пример Firmata: File > Examples > Firmata > StandardFirmata.
- Нажмите Upload.
StandardFirmata позволяет Unity (через Uniduino) читать и записывать значения пинов Arduino в реальном времени.
Если вы новичок и установка Arduino вызывает вопросы, рекомендуется пройти краткий вводный курс по Arduino (поиск «Beginner’s Guide to Arduino»). Это ускорит отладку и понимание.
Настройка проекта Unity
- Откройте Unity и зайдите Window > Asset Store в редакторе.
- Найдите плагин Uniduino и импортируйте его в проект.
- Примечание: плагин платный, но упрощает работу. Можно обойтись без него, используя SerialPort и собственную реализацию протокола, но это сложнее.
- В сцене перетащите префаб Uniduino: Assets > Uniduino > Prefabs > Uniduino.
- В панели тестирования Uniduino установите Pin D2 как INPUT и Digital; Pin A5 как ANALOG. Должны появиться значения ваших элементов управления.
ALT: Окно Unity Asset Store с выделенным плагином Uniduino.
Видео от авторов плагина демонстрирует настройку и проверку связи. На Windows иногда требуется перезапустить Unity для корректного захвата COM-порта.
ALT: Панель Uniduino в Unity: отображение цифровых и аналоговых пинов и их текущих значений.
Что мы будем управлять
Создадим простую игру: вы управляете сферой внизу экрана, уклоняетесь влево/вправо от падающих кубов. Потенциометр отвечает за горизонтальное перемещение, кнопка — за временное замедление времени (slow-motion).
Создайте новую сцену. Добавьте префаб Uniduino в иерархию.
В иерархии: Create > Sphere. С помощью вкладки Transform поместите её внизу экрана (пример координат показан на изображении).
ALT: Инспектор Unity показывает значение X у Transform для сферы, положение внизу игрового экрана.
Код: подключение Arduino к Unity
Добавим скрипт к сфере. Выделите сферу, затем Add Component > New Script, назовите sphereMover, язык C#. Нажмите Create and Add. Откройте скрипт и вставьте следующий код.
using UnityEngine;
using System.Collections;
using Uniduino;
public class sphereMover : MonoBehaviour
{
// Заголовки помогают ориентироваться в инспекторе
[Header("Arduino Variables")]
// переменная для Arduino
public Arduino arduino;
// номер пина потенциометра (публичный — можно задать в инспекторе)
public int potPinNumber;
// значение потенциометра (0 - 1023)
public float potValue;
// преобразованное значение потенциометра в позицию по X
public float mappedPot;
// номер пина кнопки
public int buttonPinNumber;
[Header("Sphere Variables")]
// границы по X, между которыми может двигаться сфера
public float leftEdge;
public float rightEdge;
// Инициализация
void Start()
{
// получаем глобальный объект Arduino и настраиваем пины
arduino = Arduino.global;
arduino.Setup(ConfigurePins);
}
void ConfigurePins()
{
// настраиваем пин потенциометра как аналоговый
arduino.pinMode(potPinNumber, PinMode.ANALOG);
// просим Arduino слать изменения аналогового пина (A5 в нашем примере)
arduino.reportAnalog(5, 1);
// настраиваем пин кнопки как входной
arduino.pinMode(buttonPinNumber, PinMode.INPUT);
arduino.reportDigital((byte)(buttonPinNumber / 8), 1);
}
void Update()
{
// читаем значение потенциометра с Arduino
potValue = arduino.analogRead(potPinNumber);
// далее мы будем ремапить potValue в значение X
}
}Обратите внимание на публичные переменные — их удобно задавать в инспекторе. После сохранения скрипта вы увидите новые поля в инспекторе у компонента sphereMover.
ALT: Инспектор Unity показывает компонент sphereMover со множеством пустых полей для настройки.
Заполните номера пинов (например, potPinNumber = 5, buttonPinNumber = 2) и границы leftEdge/rightEdge — это X-координаты, между которыми будет перемещаться сфера.
ALT: Инспектор Unity с заполненными значениями пинов и границ движения сферы.
Проверка: «первые признаки жизни»
Добавим одну строку в Update(), чтобы видеть значение потенциометра в реальном времени — это поможет убедиться, что Uniduino слушает нужный порт.
void Update()
{
// присваиваем значение с Arduino переменной potValue
potValue = arduino.analogRead(potPinNumber);
}Проверьте Uniduino в иерархии: укажите Port Name (например, COM4 на Windows). Затем запустите режим Play в Unity. Через несколько секунд potValue должен начать меняться при вращении потенциометра.
ALT: Инспектор Uniduino с полем Port Name, где указан COM-порт Arduino.
ALT: Поле potValue в инспекторе Unity меняется в реальном времени при вращении потенциометра.
Если значение не меняется — перепроверьте проводку, выбранный COM-порт и загруженную прошивку StandardFirmata.
Перевод аналогового значения в позицию: Remap
Потенциометр выдаёт значения от 0 до 1023. Нам нужно отобразить этот диапазон на координаты X сцены (например, от leftEdge до rightEdge). Для этого используется вспомогательная функция Remap.
Создайте скрипт ExtensionMethods:
using UnityEngine;
using System.Collections;
public static class ExtensionMethods
{
// Функция Remap: переводит value из диапазона [from1, to1] в диапазон [from2, to2]
public static float Remap(this float value, float from1, float to1, float from2, float to2)
{
return (value - from1) / (to1 - from1) * (to2 - from2) + from2;
}
}Теперь вернитесь в sphereMover и в Update() добавьте ремап и присвоение позиции:
void Update()
{
potValue = arduino.analogRead(potPinNumber);
mappedPot = potValue.Remap(0f, 1023f, leftEdge, rightEdge);
// назначаем X координату сферы
transform.position = new Vector3(mappedPot, transform.position.y, transform.position.z);
}Если управление кажется перевёрнутым (повёрнут влево/вправо), поменяйте местами leftEdge и rightEdge в вызове Remap.
ALT: Схема, показывающая, как значение 0..1023 сопоставляется с координатами leftEdge..rightEdge.
Кнопка: замедляем время
Добавьте в Update() проверку состояния кнопки и изменяйте Time.timeScale для эффекта slow-motion:
void Update()
{
potValue = arduino.analogRead(potPinNumber);
mappedPot = potValue.Remap(0f, 1023f, leftEdge, rightEdge);
transform.position = new Vector3(mappedPot, transform.position.y, transform.position.z);
// если кнопка нажата — замедляем время
if (arduino.digitalRead(buttonPinNumber) == 1)
{
Time.timeScale = 0.4f;
}
else
{
Time.timeScale = 1.0f;
}
}Теперь при нажатии кнопки игровой мир будет замедляться, что даёт шанс увернуться.
Добавляем врагов: падающие кубы
Создайте Cube: Create > 3D Object > Cube. На Cube добавьте компонент Rigidbody (Add Component > Physics > Rigidbody). Установите Drag = 5. В компоненте Box Collider включите Is Trigger — это позволит обрабатывать пересечения без физического отталкивания.
Создайте скрипт collideWithSphere для куба:
using UnityEngine;
using System.Collections;
public class collideWithSphere : MonoBehaviour
{
void OnTriggerEnter(Collider other)
{
Destroy(other.gameObject);
}
}Этот скрипт уничтожает объект, с которым столкнулся куб. Далее превратите Cube в префаб (перетащите его в Project panel), удалите куб из сцены.
Создайте пустой объект: Create > Create Empty, назовите Game Manager и добавьте скрипт gameManager:
using UnityEngine;
using System.Collections;
public class gameManager : MonoBehaviour
{
// префаб куба
public GameObject cube;
// параметры спавна
public int numberToSpawn;
public float lowestSpawnHeight;
public float highestSpawnHeight;
void Start()
{
for (int i = 0; i < numberToSpawn; i++)
{
Instantiate(cube, new Vector3(Random.Range(-9f, 9f), Random.Range(lowestSpawnHeight, highestSpawnHeight), 0f), Quaternion.identity);
}
}
void Update()
{
}
}В инспекторе Game Manager перетащите префаб cube в поле Cube и задайте параметры спавна. Совет: ставьте lowestSpawnHeight достаточно высоко, чтобы Uniduino успел инициализироваться и игроку дали шанс среагировать.
ALT: Инспектор Unity с компонентом gameManager и полями для префаба куба и параметров спавна.
Финал: игра готова
Запустите сцену. Кубы будут спауниться сверху и падать. Управляйте сферой потенциометром, а в трудные моменты используйте кнопку для замедления времени.
В этом проекте вы:
- Собрали простой контроллер на Arduino.
- Использовали StandardFirmata для обмена данными с Unity.
- Настроили Uniduino для взаимодействия.
- Написали скрипты для управления объектами и спавна врагов.
Идеи для расширения: добавить звуковую обратную связь, счётчик очков, уровни сложности, новые датчики (гироскоп/акселерометр), или использовать несколько аналоговых входов для дополнительных осей управления.
Частые проблемы и отладка
Значения не приходят в Unity:
- Проверьте COM-порт в Arduino IDE и в Uniduino.
- Убедитесь, что на Arduino загружен StandardFirmata.
- Если Uniduino не подключается — закройте другие программы, использующие порт (Arduino IDE Serial Monitor).
Потенциометр вращает в обратную сторону:
- Поменяйте местами leftEdge и rightEdge в Remap.
- Или переверните проводку потенциометра.
Кнопка даёт нестабильные значения:
- Используйте подтягивающий резистор 10 кОм к VCC или GND, либо включите внутренний pull-up в коде.
- Проверьте контакт на макетной плате.
Unity «теряет» порт после выхода из Play Mode:
- Иногда требуется перезапустить редактор Unity, чтобы вернуть доступ к COM-порту.
Альтернативные подходы и совместимость
- Без Uniduino: можно использовать System.IO.Ports.SerialPort в Unity и реализовать собственный протокол обмена данными (чтение аналоговых значений по serial). Потребует доп. программирования и парсинга сообщений.
- Плагины и библиотеки: помимо Uniduino есть и другие решения (например, Ardity, Uduino). У каждого свои особенности — сравнивайте совместимость с вашей версией Unity.
- Другие платы: Arduino Leonardo, Micro или платы на базе STM32/Teensy могут выступать в роли HID-устройства и напрямую эмулировать джойстик/клавиатуру. Это даёт другой подход (без Firmata), особенно для проектов, где нужен нативный ввод.
- Протоколы: рассматривайте OSC или MIDI для взаимодействия с игровыми движками или софтами (подходит, если хотите использовать контроллер в музыкальных проектах).
Ментальные модели и эвристики
- Разделение ответственности: аппаратная часть (сборка, проводка, прошивка) и программная (Unity, логика). Отлаживайте каждую по отдельности.
- Слой абстракции: Firmata/Uniduino — это абстракция, которая связывает ваши пины с объектами Unity. Если хотите гибкости и производительности, реализуйте свой протокол на serial.
- Быстрый цикл разработки: выполняйте минимальные изменения и сразу тестируйте в Play Mode. Это ускоряет поиск ошибок.
Чеклист перед первым запуском
- Arduino подключён по USB и прошивка StandardFirmata загружена
- Компоненты на макетной плате подключены согласно схеме
- Uniduino добавлен в сцену и выбран правильный COM-порт
- В инспекторе sphereMover заданы номера пинов и границы движения
- Cube превратил в префаб, Game Manager настроен
- Все скрипты сохранены и не содержат синтаксических ошибок
Критерии приёмки
- При вращении потенциометра значение mappedPot меняется и сфера перемещается по оси X.
- При нажатии кнопки Time.timeScale становится 0.4, при отпускании — 1.0.
- Кубы падают сверху и уничтожают сферу при касании (или наоборот, в зависимости от логики).
- Uniduino отображает текущие значения пинов в тест-панели.
Возможные расширения и эксперименты
- Подключить второй потенциометр для управления скоростью или высотой прыжка.
- Использовать энкодер вместо потенциометра для бесконечного вращения и дискретного шага управления.
- Добавить датчики: гироскоп для наклона, ультразвук для внешнего ввода.
- Реализовать сетевой режим: отправлять данные контроллера по UDP/OSC на другой компьютер.
- Превратить устройство в MIDI-контроллер: читать значения и слать события MIDI.
Безопасность и приватность
- Беспокоиться о безопасности в локальном проекте обычно не нужно. Если планируете обмен данными по сети, шифруйте трафик или применяйте проверку подлинности.
- Не отправляйте данные с устройств на сторонние серверы без явного согласия.
Короткая методология тестирования
- Проверка Arduino: загрузить StandardFirmata, открыть Serial Monitor (или проверить COM в IDE).
- Подключение Uniduino: убедиться, что выбран COM-порт и тест-панель показывает значения.
- Тест логики в Unity: проверять Update() наловченно — сначала вывод potValue в консоль, затем перемещение объекта.
- Интеграционное тестирование: убедиться, что управление устойчиво при длительной игре.
Небольшой словарь терминов
- Firmata — протокол, позволяющий микроконтроллеру передавать данные о пинах по serial.
- Uniduino — плагин Unity для работы с Arduino через Firmata.
- Potentiometer (потенциометр) — регулятор сопротивления, дающий аналоговый сигнал.
- Remap — математическая функция отображения значений из одного диапазона в другой.
Если хотите пойти дальше: когда подход не сработает
- Если нужен низкий уровень задержки и высокая частота обновления — Firmata + Uniduino может оказаться недостаточно быстрым. В таком случае реализуйте собственную serial-коммуникацию и минимизируйте накладные расходы в сообщениях.
- Если требуется natively распознаваться ОС как джойстик — используйте платы с поддержкой USB HID (Leonardo, Pro Micro, Teensy).
- Если контроллер должен работать на мобильном устройстве — рассмотрите Bluetooth (HC-05/06) и приём на стороне мобильного приложения.
Примеры тест-кейсов (приёмочных)
- ТК1: Потенциометр в крайнее левое положение — сфера становится в координате leftEdge.
- ТК2: Потенциометр в крайнее правое положение — сфера становится в координате rightEdge.
- ТК3: Быстрое перемещение потенциометра — перемещение сферы плавное, без «заиканий».
- ТК4: Нажатие и удержание кнопки — Time.timeScale = 0.4, отпустил — 1.0.
Заключение
Вы создали рабочий прототип контроллера на Arduino и связали его с простой игрой в Unity. Этот пример — отличная отправная точка для проектов с настраиваемыми контроллерами: от арт-инсталляций до соревнований и геймджемов. Экспериментируйте с датчиками, интерфейсами и интерактивностью — возможности почти безграничны.
Если вы собрали похожий проект — поделитесь им в комментариях или на тематических площадках. Интересно увидеть, какие творческие идеи люди реализуют с помощью Arduino и Unity!
Краткий список ресурсов для продолжения изучения:
- Arduino Official Documentation — справочник по платам и библиотекам.
- Unity Manual — разделы по Input, Scripting и Prefabs.
- Uniduino Asset Store — документация и тестовые видео.
Похожие материалы
Bluebugging: как работает и как защититься
Программирование термостата Google Nest
Как распознать вредоносные вложения в почте
Как понять, взломан ли ваш Wi‑Fi и как защититься
Защита от инсайдерских атак с программами‑вымогателями