Malmo - это основа AI для Microsoft для Minecraft, состоящая из мод для самой игры и многоплатформенной платформы для отправки входов и получения данных о мире.Непрерывная цель для цели в Мальме
Целевое назначение Minecraft является цилиндрическим. Он хранится в рыскании (влево и вправо) и шаге (вверх и вниз) вместо полного кватерниона поворота. Yaw идет от -180 градусов в крайнем левом углу и обертывается до 180 в крайнем правом углу. Шаг идет от -90, указывая прямо вверх (зенит) на 90 вниз (надир). В моем коде я храню их как Vector2
(воссозданный для работы так же, как XNA), так что X представляет собой Yaw, а Y представляет собой Pitch.
У меня возникли проблемы с созданием непрерывного прицеливания к целевому алгоритму, чтобы ИИ мог направить свою камеру на заданный рывок и шаг. Поскольку единственный способ сделать это, продолжая непрерывное движение, - это непрерывное прицеливание (установка рыскания и шаг скорости, а не значения), мне нужно многократно увеличивать рыскание и подачу в направлении цели.
Я делаю это, сохраняя целевое направление в нулевом свойстве. Если свойство имеет значение NULL, это означает, что нельзя изменить цель. В противном случае вычитайте расстояние между сохраненным значением (цель) и текущей целью (поставляемой через параметр) каждый раз при вызове метода обновления. Затем он масштабирует разницу, так что либо рыскание, либо шаг равно 1 (максимальная скорость), а другая правильная пропорция для этого. Эта пропорциональная скорость Vector2
делится на ее рыскание и шаг, а затем отправляется клиенту с помощью команд turn
и pitch
. Как только в пределах 10 градусов целевого направления, цель установлена в нуль.
На бумаге кажется, что это сделало бы цель камеры направленной прямо в направлении цели (за исключением рысканий). Тем не менее, шаг клиента обычно проходит прямо за целевое направление, несмотря на то, что метод обновления отправляет команду pitch
, которая говорит, что она идет в противоположном направлении. Это означает, что шаг как-то «застревает» в зените и надире, но фиксирует себя и «поворачивается» и застрял на противоположном полюсе через пару секунд. Количество времени, проведенного застрявшим перед поворотом, кажется, увеличивается экспоненциально (или, возможно, квадратично) каждый раз.
Вот исходный код моего прицельной метода обновления:
public void UpdateAim(Observations obs)
{
// AimTarget is a Vector2? property
if (AimTarget == null || obs == null)
{
return;
}
if (AimTarget.Value.Distance(obs.Aim) < AIM_CLOSE_ENOUGH) // < 10
{
Logger.LogInfo("Reached {0}", AimTarget.Value);
Look(Vector2.Zero);
AimTarget = null;
return;
}
double deltaYaw = AimTarget.Value.X - obs.Aim.X;
double deltaPitch = AimTarget.Value.Y - obs.Aim.Y;
// These two are stored as private Vector2 fields
deltaAim = new Vector2(deltaYaw, deltaPitch);
scaledAim = deltaAim/Math.Max(Math.Abs(deltaAim.X), Math.Abs(deltaAim.Y));
Look(scaledAim); // sets continuous aim velocity
}
И в (упрощенном) исходный код Look(Vector2)
:
public void Look(Vector2 direction)
{
// Agent is an AgentHost property
Agent.sendCommand("turn " + velocity);
Agent.sendCommand("pitch " + velocity);
}
UpdateAim()
называется 20 раз в секунду (хотя я пытался до 50 раз в секунду и до 5) во время основного игрового цикла.
В конце последнего времени я управлял AI (который застрял в надире), мои направленные данные отладки выглядели следующим образом:
// Format: (yaw, pitch)
Target Aim: (134.75, 27.90)
Actual In-Game Aim: (-6.50, 90.00) // Lines up with MC's debug screen
Delta Aim : (145.17, -62.10) // Total degrees needed to go in yaw and pitch
Scaled Aim Velocity: (1.00, -0.43)
Масштабированной скорость цель состоит в том, что подается в Look()
. Как вы можете видеть, скорость подачи была отрицательной, как и предполагалось, но фактическая цель в игре остается на уровне 90 и по какой-то причине не исправляется. Правильно ли я делаю математику?
Я тестировал это с помощью ИИ, который принимает команды с консоли, и когда я запускаю «шаг -1», за которым следует «шаг 1» (и различные значения между ними), ответ мгновенно. Возможно, у него есть отставание. Я не совсем уверен, так как тестирование с задержкой в 500 мс между циклами приводит к диким неточностям и чрезмерной коррекции, что почти невозможно отличить от этой проблемы. –