Учебник по визуальному скриптингу (Логические кирпичики)
Первые шаги: создание базового движения игрока
Lesson 3 of 10 • 20 XP
Keep your place in this quest
Log in or sign up for free to subscribe, follow lesson progress, and access more learning content.
В этом уроке мы продолжим разрабатывать базовую логику движения для нашего Игрока.
Используя Logic Bricks Cave Engine, мы создадим логику, отвечающую за передвижение персонажа. По ходу дела вы узнаете, как захватывать ввод от игрока, преобразовывать этот ввод в направление движения, контролировать скорость движения и поддерживать визуальную логику в организованном виде.
Этот урок основан на логике прыжка, созданной ранее. Теперь, вместо того чтобы реагировать только на одно нажатие клавиши, мы будем считывать несколько клавиш одновременно и использовать их, чтобы определить, куда должен двигаться Игрок.
1. Добавление Sequence
Чтобы продолжить разработку логики движения для нашего Игрока, мы узнаем, как использовать узел Sequence.
Узел Sequence позволяет создавать несколько выходов Flow из одного входа. Это полезно, потому что многие игровые системы требуют выполнения более одного фрагмента логики из одного события.
Например, наше событие On Update должно проверять логику прыжка каждую рамку, но также должно проверять логику движения каждую рамку. Вместо того чтобы создавать все в одной большой и запутанной цепи, мы можем использовать Sequence, чтобы разбить поток на несколько организованных ветвей.
Таким образом, одно и то же событие On Update может выполнять разные блоки логики каждую рамку более чистым и контролируемым способом.

2. Создание логики движения
Чтобы создать движение Игрока, мы начнем с добавления узла Events, а затем узла Active.
Узел Active проверяет, удерживается ли клавиша в данный момент. Это отличается от проверки, была ли клавиша нажата только один раз. Для движения обычно мы хотим знать, удерживает ли игрок клавишу постоянно, потому что персонаж должен продолжать двигаться, пока клавиша остается активной.
Мы сделаем это для всех клавиш движения:
- W для движения вперед
- S для движения назад
- A для движения влево
- D для движения вправо
Выход узла Active — это значение Bool. Булевская переменная может иметь только два состояния: True или False.
Когда мы преобразуем это булевое значение в Float, используя узел Bool To Float, мы получаем:
- 1, когда значение True
- 0, когда значение False
Это позволяет нам использовать состояние клавиатуры в математических операциях.
Например, мы можем вычесть значение S из значения W, чтобы вычислить движение вперед/назад. Мы также можем вычесть значение A из значения D, чтобы вычислить движение влево/вправо.
Это работает, потому что каждая клавиша возвращает либо 0, либо 1.
Например, для движения вперед и назад:
- Если W нажата, а S не нажата, результат —
1 - 0 = 1, так что Игрок движется вперед. - Если S нажата, а W не нажата, результат —
0 - 1 = -1, так что Игрок движется назад. - Если ни одна клавиша не нажата, результат —
0 - 0 = 0, так что движение по этой оси отсутствует. - Если обе клавиши нажаты, результат —
1 - 1 = 0, так что они компенсируют друг друга.
С этими результатами мы добавим узел Make Vector 3 и подключим рассчитанные значения к осям X и Z, которые будут отвечать за определение направления движения.
Теперь подключите первый выход Then узла Sequence к потоку этой логики движения, в то время как другой выход Then может продолжать использоваться логикой прыжка, созданной на предыдущем уроке.
Наконец, получите Entity, получите доступ к его Character Component и используйте узел Set Walk Direction. Подключите вектор, созданный узлом Make Vector 3, к параметру направления, чтобы компонент персонажа знал, куда должен двигаться Игрок.

Теперь нам нужно создать ограничитель, чтобы контролировать скорость движения нашего Игрока.
Вместо того чтобы определять направление движения напрямую в Set Walk Direction, мы сначала сохраним направление движения в свойстве. Это дает нам больший контроль, потому что мы сможем изменить это направление перед его применением к персонажу.
Откройте вкладку Properties, создайте новое свойство, измените его тип на Vector3 и переименуйте его в Move Dir.
Это свойство будет использоваться для хранения направления движения Игрока и послужит основой для следующих корректировок в логике.


Нажмите на значок шестеренки, отображаемый рядом со свойством, и выберите Change Type, чтобы изменить его тип.
Затем выберите Vector3.


Теперь вернитесь к Graph ваших Logic Bricks и установите свойство Move Dir, которое мы только что создали.

Подключите выход узла Make Vector 3 к значению свойства Move Dir.
Это означает, что вместо того, чтобы применять направление движения напрямую к персонажу, мы храним этот вектор в свойстве, чтобы мы могли использовать и изменить его в последующих частях логики.

Теперь, когда мы храним направление движения персонажа в свойстве Move Dir, давайте создадим еще два свойства типа Float:
- Walk Speed
- Run Speed
Эти свойства определят скорость Игрока в каждом состоянии движения.
Использование свойств здесь является хорошей практикой, потому что это облегчает последующие настройки движения. Вместо того чтобы искать жестко закодированные значения внутри графа, вы можете просто выбрать Entity и доработать скорость ходьбы и бега прямо из вкладки Properties.

Теперь создайте еще одно свойство, на этот раз типа Bool, названное Is Running.
Это свойство будет хранить состояние бега персонажа. Оно будет сообщать логике, бежит ли Игрок в данный момент или нет, что позволит нам выбрать между значениями Walk Speed и Run Speed.

Теперь добавьте узел Active, чтобы проверить, удерживается ли клавиша Shift.
Затем используйте Set Is Running, чтобы определить свойство на основе этого условия. Когда Shift активна, Is Running должно быть установлено в True, указывая на то, что персонаж бежит.

Теперь мы определим Walk Direction с использованием направления, хранящегося в свойстве Move Dir, а также применим соответствующую скорость для каждого состояния движения.
Для этого добавьте узел If, который проверяет, является ли свойство Is Running True или False.
Если результат True, получите значение Move Dir и умножьте его на свойство Run Speed.
Если результат False, получите значение Move Dir и умножьте его на свойство Walk Speed.
Наконец, подключите результат этого умножения к узлу Set Walk Direction.
Таким образом, направление движения остается прежним, но его интенсивность изменяется в зависимости от того, идет ли Игрок или бегает.

Теперь нам нужно решить небольшую проблему.
Если вы перемещаете персонажа по диагонали, вы можете заметить, что он движется быстрее, чем при движении только вперед, назад, влево или вправо. Это происходит потому, что комбинирование двух осей движения создает вектор с более большой величиной.
Например, только движение вперед создает направление вроде этого:
(0, 0, 1)
Но движение вперед и вправо одновременно создает нечто подобное:
(1, 0, 1)
Этот диагональный вектор длиннее, чем вектор по одной оси, что заставляет персонажа двигаться быстрее по диагонали.
Чтобы исправить это поведение, мы нормализуем вектор направления перед тем, как сохранить его в свойстве Move Dir.
Сначала получите Length вектора, созданного узлом Make Vector 3.
Затем добавьте узел If, чтобы проверить, больше ли это значение 0.
Эта проверка важна, потому что мы не должны нормализовать пустой вектор. Вектор с длиной 0 означает, что ни одна клавиша движения не нажата, так что нет направления для нормализации.
Если условие истинно, используйте узел Normalized, чтобы получить нормализованную версию вектора.
В противном случае используйте оригинальный вектор.
Наконец, подключите результат к узлу Set Property для Move Dir.
Это сохраняет направление движения, но сохраняет его величину постоянной, обеспечивая, чтобы персонаж двигался с одинаковой скоростью в каждом направлении.

3. Использование событий
Существует более организованный способ структурировать поток нашей логики внутри Logic Bricks.
Помимо комментариев и узла Sequence, мы также можем использовать Events, чтобы сделать систему более чистой и понятной.
События позволяют вам разделить определенный блок логики и вызывать его из другого места в графе. Это особенно полезно, поскольку ваш граф растет, потому что это избегает прямого соединения всего с On Update в одной большой цепи.
Теперь давайте создадим новое событие под названием Move Player.

Затем подключите это событие к потоку блока логики движения Игрока.

Теперь, вместо того чтобы держать всю логику движения прямо подключенной к On Update, мы можем просто вызвать событие Move Player внутри последовательности On Update.
Это делает поток более чистым, модульным и легче понимаемым, особенно по мере усложнения логики проекта.

На этом этапе Игрок уже имеет базовую систему движения, созданную с помощью Logic Bricks.
Логика теперь проверяет клавиши движения, вычисляет направление движения, нормализует направление, чтобы избежать более быстрой диагональной скорости, сохраняет его в свойстве Move Dir, проверяет, бежит ли игрок, применяет правильную скорость и, наконец, отправляет результат в Character Component через Set Walk Direction.