Привет. Недавно поставил перед собой задачу сделать платфомер с управлением в стиле Hot-Seat. Я рассматривал конкретно модель, где один игрок играет на клавиатуре, а второй на геймпаде.
Однако поискав в интернете как это сделать грамотно я не нашёл ничего полезного, поэтому пришлось создавать идею самому.
Предупреждаю! Я просто делюсь своим опытом. Я уверен, что есть решение намного практичнее и удобнее, этот пост больше для начинающих.
Подготовка
Изначально я хотел использовать стандартный Input Manager, однако столкнулся с проблемами обозначения, что за что отвечает, поэтому эта идея была быстро отброшена.
Чуть позже я нашёл его обновлённую версию от самих разработчиков Unity - Input System. Как я понял, она является предустановленной вместе с самой Unity, однако почему-то стандартным методом настройки управления всё таки остался Input Manager. Не знаю с чем это связано.
Разработка, настройка управления, подключение к скриптам
Итак, создаём проект в Unity.
Когда Unity запустился сразу переходим в Window -> Package Manager и сверху Packages меняем на Unity Registry и справа в строке поиска вводим Input System. Импортируем в наш проект.
После установки нам высвечивается ошибка, которая гласит, что в проекте на данный момент появилась новая система управления, однако она не задана в настройках и работать не будет. Нажимаем YES. Проект перезапустится а новая система управления уже окажется готовой к работе. Для проверки, что всё прошло правильно, можем зайти в Edit -> Project Settings -> Input Manager. Тут должна быть плашка в которой написано, что новый способ управления настроен, а этот работать не будет. Однако в этом случае будут вылетать ошибки, поэтому лучше перейти в Player и пролистать до пункта "Active Input Handling" и поставить там значение "Both".
Я создал небольшую сцену с двумя квадратиками - это и есть наши игроки. Теперь нам нужно настроить им управление. Создадим файл управления
Когда мы два раза кликнем на него, у нас откроется вот такое меню.
Всё что описано дальше - скорее всего не самый лучший, но при этом рабочий способ. Лично я создаю две "карты" управления. Одну под клавиатуру, другую под геймпад. Выглядит это следующим образом
На скрине с управлением для геймпада видно настройку самого действия Move - это у нас должно быть значение (Value) при этом тип этого значения должен быть Axis. Чтобы сделать блок управления клавиатуры как на скрине нужно нажать "+" рядом с Move и там добавить positive/negative binding.
После того как мы всё настроили нам необходимо сохранить и создать C# скрипт с этим управлением.
Для этого сначала нажимаем "Save Asset", после в инспекторе нажимаем на наш файл Input System, ставим галочку "Generate C# Class" и подтверждаем. Появится C# файл, который и будет управлять этим всем.
Примечание. У вас есть возможность нажать Auto-Save и тогда эта процедура будет делаться за вас. Но лично у меня макбук зависал после каждого изменения в файле Input System на пару секунд. Не страшно, но раздражает, когда надо добавить много действий, поэтому отказался от этого.
Наконец пришло время перенести это всё в наш скрипт и радоваться. Создаём C# скрипт, который будет нашим управлением.
Вот весь код:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PC : MonoBehaviour
{
PlayersContoll _PC; // тут будет храниться наш скрипт управления
[SerializeField]
bool isGamepad; // засчёт этой переменной будем контролировать, какой персонаж управляется геймпадом, а какой клавиатурой
private void Awake()
{
_PC = new PlayersContoll();
/*
Если вам нужно сделать действия не постоянно выполняемые, а только при нажатии на кнопку (например прыжок), то делаем так:
if (isGamepad)
{
_PC.Gamepad.Jump.performed += context => Jump();
}
--//-- для клавиатуры по аналогии с движением
*/
}
private void OnDisable() // Отключаем управление - на случай катсцен, диалогов и прочего
{
_PC.Disable();
}
private void OnEnable() // Обратно включаем управление
{
_PC.Enable();
}
private void Update()
{
Move();
}
void Move()
{
float dir;
if (isGamepad) // Проверяем, геймпадом ли управляется этот объект
{
dir = _PC.Gamepad.Move.ReadValue<float>();
}
else
{
dir = _PC.Keyboard.Move.ReadValue<float>();
}
print(dir);
gameObject.transform.Translate(new Vector2(dir, 0));
}
}
Если коротко, то сначала мы объявляем переменную, где будет храниться скрипт управлением (8 строка) а также переменную типа bool, которая определит тип управления этим персонажем (11). Потом в блоке Awake присваиваем этой переменной скрипт (15). Если есть какие-то действия, которые выполняются по нажатию на кнопку - сразу же тут обрабатываем подписку на эти события (17-24). После этого делаем обработку движения, с использованием той самой переменной, которая определяет тип управления (45-52).
После выполнения этих действий накидываем скрипты на объекты, ставим в одном из них галочку в пункте "isGamepad" и радуемся, ведь теперь у нас один игрок управляет с клавиатуры одним объектом, а другой с геймпада другим объектом.
Рассуждения насчёт метода
Данный ассет имеет возможность настройки схемы управления. Этот пункт находится чуть выше карт при создании управления. Возможно можно как-то сделать через это, но у меня не получилось.
Также, возможно более практичной будет другая возможность ассета. Он позволяет не просто принимать в скрипте значения передвижения (как у нас в строках 45-52), а наоборот, передавать значения в определенный скрипт из самой системы. Возможно можно сделать таким образом.
С помощью ассета можно отследить серийники устройств, их имена в интерфейсе и прочее. Скорее всего с помощью этого можно сделать управление используя два геймпада, но я в это не лез, ибо нет второго геймпада для тестов, а мучаться с эмуляторами желания нет.
Заключение
Буду благодарен за любой фидбек в комментариях, будь то критика моего метода или предложения по его улучшению. Я понимаю, что метод не идеален, но для первой работы с Hot-Seat результат меня вполне устроил.