Читать книгу Делаем PC игру вместе - Ар'лан ис'Дрекхэм - Страница 12
«Делаем PC игру вместе»
9. Движенине
ОглавлениеДобавим следующую строку кода, которая формирует локальную переменную вектора в пространстве, в трех координатах – X, Y, Z:
Vector3 movement = new Vector3 (offsetX, 0, offsetZ);
Vector3 (вектор 3) в Unity3d фактически представляет собой просто 3 собранные вместе переменные типа float описанные ранее, но используется для описания положения в пространстве и направления движения.
Мы видим новый оператор под названием new (новый), этот оператор нужен для создания нового экземпляра типа данных. В данном случае мы создаем новый вектор с указанием двух переменных offsetX и offsetZ. Отсутствует переменная Y, которая описывает движение вверх-вниз, и сейчас не нужна.
Правильные направления по осям в Unity3d можно легко запомнить используя ассоциативное запоминание. Например, чтобы запомнить, что координата Z (зэт) это движение вперед, то можно представить себе, что Z похоже на зигзагообразное движение лодки по воде уходящей вдаль, т.е. плывем вперед (вперед-назад). Y (игрек) похожа на песочные часы, которые сыпятся только вниз (вверх-вниз), а для X (икс) остается только влево-вправо.
Сейчас мы сделали вектор движения movement (движение), который будет ответственным за движение нашего персонажа вперед-назад и влево-право, в зависимости от того какие клавиши на клавиатуре будет нажимать играющий человек. Но сейчас при текущем нашем коде движение вперед-назад и влево-право будут происходить медленнее, чем движения по диагонали. Это будет происходить потому, что при движении по диагонали будут учитываться значения смещений и offsetX и offsetZ вместе. Чтобы сделать движение по всем направлениям равномерным нужно добавить такой код следующей строкой:
movement = Vector3.ClampMagnitude (movement, speedfast);
ClampMagnitude это внутренний метод Unity3d, который ограничит величину нашего вектора движения так, что скорость перемещения будет равномерной по всем направлениям.
Добавим такую строчку кода:
movement. y = gravity;
Чуть выше мы не использовали переменную Y, которая нужна для движения вверх и вниз. Сейчас мы добаваляем и ее. В нашем векторе movement есть 3 переменные и мы можем получить или задать каждую из них в отдельности, сейчас это выглядит как movement. y, т.е. мы задаем эту переменную равной gravity (гравитация) для того чтобы наш будущий игрок мог свободно падать вниз если у него не будет опоры под ногами.
Следующий важный нюанс состоит в том чтобы наш будущий игрок мог двигаться одинаково на разных по мощности компьютерах, при разной скорости работы игры, при разных FPS игры и т. п. Для этого дальше напишем такую строчку кода:
movement = movement * Time.deltaTime;
В данной строке кода мы увязываем наш вектор движения movement через класс Time (многозадачный класс категории игрового времени) со временем рендеринга (визуализации) предыдущего кадра – deltaTime. Таким образом, любое движение в игре сможет рассчитываться вне зависимости от конкретного компьютера и его мощности. Используйте умножение на Time.deltaTime всегда в любом коде основанном на каком-то изменении значений во времени.
Также в языке C# предусмотрена возможность записи последней строки кода, так сказать, укороченно, что мы и сделаем:
movement *= Time.deltaTime;
В таком виде строка кода полностью соответсвтует предыдущей, так мы ее и оставим.
Теперь нужно «подковать еще одну ногу», а именно, наш персонаж скоро сможет двигаться, но как только он повернется его движение нарушится, т.е. персонаж будет смотреть куда-нибудь в сторону, а двигаться будет продолжать строго вперед-назад, влево-вправо. Чтобы такого не было нужно преобразовать вычисления нашего вектора movement из локальных координат в глобальные. Запишем далее такую строку:
movement = transform.TransformDirection (movement);
Слово transform это ссылка на соответствующий компонент, который находится на нашем игровом объекте Player. Здесь такая же технология как и с GetComponent <> () описанным ранее. Если после знака равенства сразу пишется transform или GetComponent <> (), это означает, что операции производятся с текущим игровым объектом на котором находится наш сценарий кода. TransformDirection () это метода Unity3d преобразующий наш вектор в мировые координаты (глобальные). Коротко поясню, что мировые координаты это основа всей 3д сцены среды разработки Unity3d, и они неизменны. А локальные координаты принадлежат какому-либо объекту сцены и постоянно изменяют свои направления, в зависимости от вращения этого объекта.
Теперь движения нашего персонажа вперед-назад, влево-вправо будут происходить в соответствии с его поворотом.
Программа движения персонажа готова и нужно ее исполнить, вернее применить к нашему игровому объекту Player. Для этого сообщим наш вектор движения компоненту CharacterController используя его внутренний метод Move (Двигать), добавим строчку кода:
CharControl.Move (movement);
Таким образом, наши строчки кода запускаясь бесконечно каждый кадр в методе Update () будут считывать нажимаемые игроком клавиши, формировать вектор направления и скорости передвижения игрока и двигать его. Теперь весь написанный код выглядит так:
using UnityEngine;
public class FPCharacter: MonoBehaviour
{
public float speed = 2.0f;
public float speedfast = 50.0f;
public float gravity = -9.8f;
CharacterController CharControl;
float _speedfast;
void Start ()
{
CharControl = GetComponent <CharacterController> ();
}
void Update ()
{
if (Input.GetKey (KeyCode. LeftShift))
{
_speedfast = speedfast;
}
else
{
_speedfast = 1;
}
float offsetX = Input.GetAxis («Horizontal») * speed * _speedfast;
float offsetZ = Input.GetAxis («Vertical») * speed * _speedfast;
Vector3 movement = new Vector3 (offsetX, 0, offsetZ);
movement = Vector3.ClampMagnitude (movement, speedfast);
movement. y = gravity;
movement *= Time.deltaTime;
movement = transform.TransformDirection (movement);
CharControl.Move (movement);
}
}
Сохраним наш сценарий и переключимся в редактор Unity3d.