Подробный список изменений: - Перенесены эффекты частиц из C#-кода в готовые префабы-ассеты (Vfx Prefabs) в папке Assets/Resources/Vfx/ с автоматической генерацией материалов в Editor. - Исправлены ошибки duration на играющих системах частиц и розовые текстуры в GameVfxService.cs. - Исправлена навигация и фокус кнопок на оверлеях ContinueGameOverlay и PrizeResultOverlay с автоматическим подсвечиванием кнопок лимонно-зеленым цветом при фокусе и проигрыванием звука. - Добавлена проверка настроек в GameplayHudController.cs для скрытия ContinueGameOverlay, если продолжение игры отключено. - Расширен сбор статистики: создана структура GameplaySessionRecord, добавлена история до 50 раундов в PrizeSessionStateService и JsonPrizeSessionStateRepository, выведен расчет средних показателей и список 5 последних раундов в сервисной статистике. - Повышена надежность COM-транспорта: добавлен sleep (80мс) в Dispose для graceful shutdown потоков, реализован цикл переподключения до 10 попыток при обрыве связи. - Интегрированы настройки громкости с микшером: изменен шаг изменения громкости на 5% (0.05) для удобства, добавлен статус-чек и логи в ApplyServiceVolumes, расширены юнит-тесты на GetFloat параметры. - Созданы новые архитектурные гайды по аппаратному COM-транспорту и призовой экономике автомата в папке GUIDES/architecture/. - Оптимизирован и обновлен RAG-индекс проекта.
5.3 KiB
Полное руководство по новому Input System
В Unity старая система Input.GetKey() заменена на современную, модульную Input System (UnityEngine.InputSystem). Она решает проблемы поддержки множества геймпадов, кроссплатформенности и переназначения клавиш.
1. Быстрый способ (Прямое чтение, как в старой системе)
Хотя это не самый гибкий способ, он удобен для быстрого прототипирования. Мы обращаемся к текущему активному устройству (Keyboard.current, Gamepad.current).
using UnityEngine.InputSystem;
public void Update()
{
// Важно проверять на null, т.к. клавиатуры может не быть (на мобилках, консолях)
if (Keyboard.current != null)
{
if (Keyboard.current.spaceKey.wasPressedThisFrame)
{
Jump();
}
}
if (Gamepad.current != null)
{
// Чтение стика (возвращает Vector2 от -1 до 1)
Vector2 moveInput = Gamepad.current.leftStick.ReadValue();
}
}
2. Правильный способ (Input Actions Asset)
Рекомендуемый подход — создать файл .inputactions через редактор (Create -> Input Actions). В нем вы задаете "Действия" (Actions), например "Move" или "Jump", и привязываете к ним кнопки с разных устройств (Пробел на ПК, Кнопка А на Xbox, Экранный стик на телефоне).
Вариант 2А: Генерация C# класса (Рекомендуется для Zenject)
- В инспекторе файла
.inputactionsпоставьте галочкуGenerate C# Class. - Создайте класс (например,
PlayerControls).
public class PlayerInputHandler : MonoBehaviour, IDisposable
{
private PlayerControls controls;
private void Awake()
{
// Инициализируем сгенерированный класс
controls = new PlayerControls();
// ПОДПИСЫВАЕМСЯ НА СОБЫТИЯ
// performed - кнопка нажата (и прошла порог чувствительности)
controls.Gameplay.Jump.performed += OnJumpPerformed;
// canceled - кнопка отпущена
controls.Gameplay.Jump.canceled += OnJumpCanceled;
}
private void OnEnable()
{
// Важно: экшены по умолчанию выключены!
controls.Gameplay.Enable();
}
private void OnDisable()
{
controls.Gameplay.Disable();
}
private void OnJumpPerformed(InputAction.CallbackContext context)
{
Debug.Log("Прыжок!");
}
private void Update()
{
// Чтение значений (например, вектора движения) в Update
Vector2 movement = controls.Gameplay.Move.ReadValue<Vector2>();
MoveCharacter(movement);
}
public void Dispose()
{
controls?.Dispose();
}
}
3. Обработка виртуального / аппаратного ввода (COM-порты)
В проекте "Danro Jump" есть ComControllerInputBridge, который принимает сигналы от реального "железного" автомата через COM-порт.
Как обмануть Unity и заставить её думать, что нажата физическая кнопка геймпада? В Input System можно программно создавать виртуальные устройства и посылать в них события.
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.LowLevel;
public class VirtualGamepadEmulator
{
private Gamepad virtualGamepad;
public void Initialize()
{
// Создаем виртуальный геймпад в системе
virtualGamepad = InputSystem.AddDevice<Gamepad>("Virtual Gamepad");
}
// Этот метод вызывается, когда по COM-порту приходит сигнал
public void TriggerVirtualJump()
{
if (virtualGamepad == null) return;
// Генерируем событие "Кнопка А (южная кнопка) нажата"
InputSystem.QueueStateEvent(virtualGamepad, new GamepadState
{
buttons = (uint)GamepadButton.South
});
}
public void Cleanup()
{
if (virtualGamepad != null)
{
InputSystem.RemoveDevice(virtualGamepad);
}
}
}
Important
Если вы генерируете события ввода из фонового потока (от COM-порта), функция
InputSystem.QueueStateEventявляется потокобезопасной, но вызовы любых других Unity API (например, перемещение объекта) должны быть переданы в главный поток!