Danil Iarosh 839a68aef1 Improve VFX, UI overlays, session statistics, COM reliability, audio mixer, and expand architecture guides
Подробный список изменений:
- Перенесены эффекты частиц из 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-индекс проекта.
2026-07-03 15:04:08 +03:00

5.3 KiB
Raw Permalink Blame History

Полное руководство по новому 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)

  1. В инспекторе файла .inputactions поставьте галочку Generate C# Class.
  2. Создайте класс (например, 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 (например, перемещение объекта) должны быть переданы в главный поток!