Я работаю над игрой, в которой игрок может подбирать предметы, используя что-то вроде луча трактора, и носить их с собой.
Привлечь объект к центру луча несложно. Но как только объект окажется достаточно близко к центру, мне нужно держать его там, пока игрок движется, с чем у меня проблемы. Я могу придумать два способа сделать это, и у обоих есть проблемы:
Обновляйте позицию объекта всякий раз, когда позиция игрока изменяется, сохраняя его в центре луча.
Обновите скорость объекта, чтобы он указывал прямо на центр луча, чем дальше, тем больше скорость.
Перемещение и вращение прекрасно работают с обоими подходами, но физика неверна, когда переносимый объект сталкивается с другими объектами:
При первом подходе физика полностью игнорируется. Носимый предмет просто отталкивает что-либо с пути. Это потому, что изменение положения должно быть сделано только как часть мировой физики, основанной на скорости.
При втором подходе физика в основном ведет себя так, как должна, но слишком остро реагирует. Проблема в том, что для того, чтобы удерживаемый объект находился в центре луча, даже когда он вращается и двигается, мне нужно использовать высокие значения скорости. Поэтому, как только переносимый объект касается другого, он получает слишком большую скорость от столкновения.
Как я могу реализовать это правильно? Мое лучшее предположение сейчас состоит в том, чтобы перейти ко второму подходу и добавить специальную обработку для переносимых объектов к мировой физике, уменьшая скорость до нормальных значений для столкновений или когда игрок прекращает нести их. Но это похоже на довольно неумелый обходной путь.
Изменить: добавление псевдокода, чтобы проиллюстрировать, как он работает прямо сейчас (это будет второй подход выше)
void attract_object(object, ticks) {
Vector distance = beam_center - object.center;
// If the object is not close to the beam center, attract it slowly
if (magnitude(distance) > 10) {
object.velocity += distance.normalized() * ticks * 0.1;
return;
}
// Here comes the part we're talking about. That magic 0.5 is just high enough
// that the object isn't lost while moving around. But it's still so high that
// other objects are repelled with way too much force.
object.velocity = distance * ticks * 0.5;
}
Из того, что я вижу, это происходит, когда переносимый объект отталкивает другой объект:
- Несущийся объект сталкивается с другим объектом
- Скорости объектов распределяются правильно, поэтому переносимый объект отталкивается от центра балки в процессе
- Приведенный выше код заставляет переносимый объект возвращаться в центр балки с такой большой скоростью, что он быстро туда возвращается
- Когда переносимый объект движется обратно к центру луча, половина его высокой скорости передается другому объекту, сильно его отталкивая. Поскольку начальная скорость переносимого объекта кажется нормальной, я могу себе представить, что шаги с 2 по 4 повторяются многократно, создавая такую высокую скорость.
Это кажется причиной. Я не могу придумать хороший способ исправить это :(
Ответы:
По сути, вы ищете, чтобы объект с «лучами» вел себя точно так, как если бы вы хватали его руками.
Один из вариантов - сделать так, чтобы он разделял скорости ускорения и ввода «руки», которая его удерживает, вместо того, чтобы регулировать ее скорость, чтобы заполнить промежуток центром балки.
Допустим, центром луча является удерживающая рука. если ваш персонаж поворачивается на 90 градусов влево за 1 секунду, то скорость руки будет равна:
If R = length of the arm: which is the radius of the rotation circle
Сделайте это время elapsedTime кадра, чтобы найти скорость, которую вы должны применить к вашему объекту. Найдите горизонтальную нормаль к лучу, чтобы найти вектор направления.R^2 *PI /4 would be the distance traveled over a second.
Я хочу сказать, что вам не нужно решать проблемы, если вы попробуете другие реализации, которые не будут вызывать это в первую очередь.
Я бы поиграл с гравитационным пистолетом в HL2, чтобы получить вдохновение для решения этой проблемы, но у меня есть другие планы на сегодня.
РЕДАКТИРОВАТЬ: я извиняюсь, я думал, что это было для 3D лучевой пистолет, но это по сути то же самое с 2D, за исключением различий осей (и нет сложной геометрии)
источник
Как насчет добавления пружинного соединения, т. Е. Заставить перемещаемый объект вернуться в положение для переноски на основе расстояния, но все же позволить ему отталкиваться твердыми предметами (например, стенами).
Постоянно регулируйте скорость переносимого объекта (изменяя ускорение в зависимости от положения / расстояния), чтобы он указывал на положение луча трактора (т. Е. Ваш второй заход на посадку). Если объект отодвинут слишком далеко, разорвите соединение (и объект).
Я не совсем уверен, почему вам нужны высокие скорости. В частности, случай «игрок отпускает» указывает на то, что ваша скорость вращения может быть слишком высокой или нереальной. Также не забывайте такие вещи, как сопротивление воздуха и гравитация.
Изменить: Учитывая обновленный код, проблема довольно тривиально найти:
Проблема здесь заключается в том, что расстояние до объекта до его цели постоянно слишком велико (то есть
> 10
). Пока это условие верно, его скорость просто увеличивается снова и снова (то есть до бесконечности).Два возможных решения для этого:
Определите максимальную скорость:
Применяйте фиксированную скорость вместо ускорения:
Просто ускорение, находясь слишком далеко, определенно является неправильным подходом. Важно потянуть пружину или резинку: не имеет значения, держите ли вы его в течение одной секунды или одной минуты. В конце он будет ускоряться таким же образом (учитывая, что он не находился в движении и другие силы не приложены).
источник