Разработка игры в Unity3D под геймпад +10


Для работы на конкурс была поставлена задача: спроектировать небольшую игру про космос, которую дети будут проходить порядка 8 минут. И было одно но. Детям должно быть интересно!


Так как пожертвовать клавиатурой на управление было слишком жалко (да и не так это интересно), всё управление планировалось сделать через геймпад. О том, как прикрутить в Unity3d геймпад и пойдёт речь.



Немного о проекте



Первое, что пришло в голову про космос, так это управляемый робот. Развивая эту мысль дальше, игра стала про робота, который на Луне должен найти батарейку, чтобы зарядить лазерную станцию и спастись от приближающейся кометы. Разумеется все нужно было делать на время (до 8-ми минут).


(На удивление детям игра понравилась, в том числе за управление, но об этом ниже).


Картография


Для создания карты с небольшими закоулками и большим соответствием Луне, картой является элемент Terrain, с горами, которые нужны как препятствия и ограничения уровня.



Чтобы уровень был достаточно долгим, робот находится в противоположном углу от батарейки, которая крайне мала, чтобы увидеть издалека. Размер выбран не случайно, так как не позволяет увидеть батарейку заранее издалека.


Управление


Контроль за руками


Так как у робота две руки, как и количество "грибков" в геймпаде, то разумно этим воспользоваться.


И вот тут начинаются сложности. Дело в том, что первый "грибок" работает (хоть и со скрипом) так же, как и "Mouse X" и "Mouse Y", но второй никак не отзывался по нажатию. Тогда, сев за гугл, прочитал о том, как Unity получает входные управляющие данные. Там и лежит ответ на вопрос, как заставить работать второй (правый) "грибок".


Заходим Edit > Project Settings > Input



Нажали? Тогда должен появиться InputManager в окне Inspector



В начале будет 18 входных параметров, но нам нужно больше. Потому у меня 22 (на ось X и ось Y для второго "грибка" геймпада и ещё два, чтобы обособить имя обращения к первому "грибку").


Дальше по аналогии с движением мышки (Mouse X) заполняем и переименовываем новые входные значения (имя крайне важно, так как в программе именно к нему вы и обращаетесь).



Код для управления руками

lp_right.transform.Rotate (0, Input.GetAxis ("Hor2_j"), 0);
yr += Input.GetAxis ("Hor2_j");


lp_right.transform.Rotate (Input.GetAxis ("Vert2_j"),0, 0);
xr += Input.GetAxis ("Vert2_j");


lp_left.transform.Rotate (0, Input.GetAxis ("Hor_j"), 0);
yl += Input.GetAxis ("Hor_j");


lp_left.transform.Rotate (Input.GetAxis ("Vert_j"),0, 0);
xl += Input.GetAxis ("Vert_j");


Передвижение


Стоит помнить, что передвижение по координатам плохо скажется на игре, так как карта построена на Terrain. Потому было принято решение использовать физику. Это увеличивает интерес прохождения с одной стороны, а с другой решает несколько проблем сразу (неровное перемещение, скачки, вылет за ограждения).


А значит нужен Rigidbody, который нужно поместить на робота, а дальше на ваш вкус (в проекте выставлена масса 100, остальное осталось не тронутым).


В коде будут только два фокуса. Первый — GetComponent(), чтобы работать именно с Rigidbody и Addforce. Второй — математический. Нужно не только знать, куда хочет робот, но и знать, куда он смотрит. Для этого обращаемся к transform.eulerAngles.y, переводим в радианы и берем косинус и синус для координат x и z соответственно.


Перемещение робота
y=bot.transform.eulerAngles.y*(Mathf.PI/180);
if(Input.GetKey(KeyCode.JoystickButton4)||Input.GetKey(KeyCode.JoystickButton0))
{
    s="Go_to";
    bot.GetComponent<Rigidbody>().AddForce(new Vector3(Mathf.Cos(y),0,-Mathf.Sin(y))*15);
}
if(Input.GetKey(KeyCode.JoystickButton5)||Input.GetKey(KeyCode.JoystickButton2))
{
    s="Go_back";
    bot.GetComponent<Rigidbody>().AddForce(-new Vector3(Mathf.Cos(y),0,-Mathf.Sin(y))*15);
}
if(Input.GetKey(KeyCode.JoystickButton6)||Input.GetKey(KeyCode.JoystickButton3))
{
    s="Turn_left";
    bot.transform.Rotate(0,-0.5f,0);
}
if(Input.GetKey(KeyCode.JoystickButton7)||Input.GetKey(KeyCode.JoystickButton1))
{
    s="Turn_right";
    bot.transform.Rotate(0,0.5f,0);
}

Как можно заметить, в действиях указаны по две кнопки. Это сделано на случай, если бампера (L1,L2,R1,R2) сломаются/залипнут при многократном использовании.


Время


Для уточнения настоящего времени в Unity можно использовать System.DateTime.Now, чтобы посчитать в секундах, сколько времени прошло от начала дня. Такой способ ограничения времени имеет недостаток — переход часов с 23:59 на 00:00, но так как игра на раз и конкурс будет проходить днем, то можно пренебречь


А если нельзя

Советов два


  • Считайте вместе с днем, месяцем и годом. Когда то видел такую функции в TurboC++, которая выдает количество секунд, прошедших с 1 января 1970
  • Прочитайте про таймеры и вызывающие функции в C#

Ограничение по времени тогда можно считать, как разницу во времени после запуска скрипта (void Start()) и тем, что сейчас (Update)


Код
void Start () {
    time = System.DateTime.Now.Hour * 3600 + System.DateTime.Now.Minute * 60 + System.DateTime.Now.Second;
}
void Update () {
    win = PlayerPrefs.GetInt ("win");
    lose = PlayerPrefs.GetInt ("lose");
    t = System.DateTime.Now.Hour * 3600 + System.DateTime.Now.Minute * 60 + System.DateTime.Now.Second;
    if((win+lose)==0) PlayerPrefs.SetInt("time",480-(t-time));
    if((480-(t-time))==0) PlayerPrefs.SetInt ("lose",1);

Послесловие


Детям игра понравилась, так как робот перемещался с ускорением, чем все охотно пользовались.


Особенно было интересно поймать батарейку до того, как ты в неё врежешься, так как она тоже Rigidbody и получит направление движения. В сочетании с медленным перемещением рук, получилось очень даже неплохо.


Надеюсь, что данная статья поможет вам не сидеть до поздней ночи, прикручивая геймпад к вашему проекту!


P.S. Собрано, сделано и проверено для Unity3d 5.0

-->


К сожалению, не доступен сервер mySQL