@fridriekh
Фулл-тайм эникей

Как научить ботов учитывать гравитацию планеты при стрельбе?

Боты довольно точно стреляют в пустом пространстве, но постоянно мажут, если на стрельбу начинает влиять гравитация

Скрипт гравитации взят отсюда.

c2dd170f6d054972903b92f6aef8e145.png
  • Вопрос задан
  • 542 просмотра
Решения вопроса 1
@0x131315
По поводу скрипта - он странный:
1) Он работает только для обьектов, которые участвуют в столкновениях.
2) Он не учитывает дистанцию до центрального тела, только его массу, и работает только для случаев, когда дистанция между противниками в тысячи раз меньше дистанции до центрального тела, т.е. более-менее точен где-то на задворках звездной системы, вдали от звезды. На более ближних дистанциях начинает безбожно врать.
3) Он наполняет обьектами массив, который не особо нужен скрипту для работы, который нигде не очищается. Это - утечка памяти.
4) Его можно прикладывать только к одному телу - центральному. Иначе это умножает утечку памяти и сильно расходует процессор. В некоторых случаях его можно заменить триггером. И часто его оптимизируют, вызывая раз в несколько десятков кадров, а не каждый кадр. Также пишут, что указание маски слоя в Physics.OverlapSphere повышает эффективность работы.

По поводу утечки.
Не знаю тонкостей unity, не могу сказать точно, насколько она серьезна. Но возможны два варианта:
1) обьект скрипта пересоздается каждый кадр, и время от времени устаревшие экземпляры собирает сборщик мусора.
Тогда утечка равна размеру массива помноженному на количество кадров в секунду и на таймаут сборщика мусора.
При условии, что скрипт используется только на одном обьекте (надеюсь ты не додумался применить его ко всем обьектам?), для 1000 обьектов в сцене, 60фпс и 10 секундном таймауте сборщика мусора, утечка составит 5..50Мб - именно столько памяти игра будет отьедать впустую, никуда не используя, только на один экземпляр этого скрипта.
Если скрипт применен к 10 обьектам, утечка увеличится до 50..500Мб.
А если обьектов 1000?
Так и рождаются игры, которые требуют 16Гб оперативки.
Это не говоря о бесполезной трате процессорных ресурсов: если по глупости применить скрипт ко всем обьектам, эффективно работать он будет только на одном, но жрать память и процессор будет за всех.
На 1000 обьектах потребление процессора этим скриптом увеличится в 1000000 раз: 1000 скриптов должны будут каждый обработать по 1000 обьектов.
Так рождаются игры, которые требуют топовое железо.
Всего 2 легкие ошибки с одним скриптом (далеко не основным) - и такой потенциал! :)
2) Используется один экземпляр скрипта, он не пересоздается каждый вызов.
Тогда обьем массива каждую секунду умножается на фпс, пока массив не забьет всю память.
И сборщик мусора тут не поможет, т.к. скрипт существует пока существует основной обьект, т.е. пока загружен уровень - всю игровую сессию.
Для тех же условий утечка в первую секунду составит 0,5..5Мб, и каждую секунду будет увеличиваться на столько же. За час игры утечка составит от 2 до 20Гб, в зависимости от размера структур.
Утечка процессора останется той же, что и в первом варианте.

Твой вариант походу первый, иначе бы скрипт отработал ровно один раз, и гравитация после первого кадра пропала: массив используется для проверки тел, к которым еще не прикладывалась гравитация.
А это не так - раз есть постоянная ошибка, гравитация работает дольше одного кадра.
Кстати, проверка эта лишняя, в документации ее нет.

По поводу ошибок прицеливания: введи поправки на гравитацию при прицеливании.
Не факт, что это тебе поможет, все-таки скрипт у тебя кривой, и непонятно правильно ли ты его используешь - каковы максимальные дистанции между противниками, каковы минимальные дистанции от противников до центрального тела, каков размер центрального тела, как создаются снаряды (независимыми или привязанными к тому, кто выстрелил), как задается их скорость (постоянная или относительно скорости выстрелившего), какова скорость снаряда и цели.
Но самое простое:
dy=g*t*t/2
t=l/v
dy - величина смещения снаряда гравитацией на текущей дистанции
g - величина гравитации, локальная (вблизи точки выстрела). В твоем скрипте гравитация постоянна, не зависит от координат, и равна массе центрального тела, значит вместо g можно подставить массу центрального тела.
t - время полета снаряда
l - прямая дистанция до противника.
v - глобальная скорость снаряда (относительно мира).
Ограничения:
Локальная гравитация неприменима, если дистанция сравнима с расстоянием до центрального тела - там нужен дополнительный учет кривизны поля гравитации. Гравитация в разных точках пути снаряда будет разная, а это сильно снизит точность, особенно на больших дистанциях - на много порядков.
Прямая дистанция неприменима, если дистанция сравнима с расстоянием до центрального тела - там нужен дополнительный учет кривизны поля гравитации. Дистанция будет не прямой, а дугой, и значит снаряд пройдет больше расстояния, лететь будет дольше, и поправка нужна больше.
Если время полета больше нескольких секунд, придется учитывать влияние гравитации на скорость снаряда. Снаряд будет ускоряться или замедляться гравитацией, а значит точность с дистанцией начнет быстро падать.
Если скорость цели сравнима со скоростью снаряда - придется учитывать, что цель движется. Пока снаряд летит в точку прицеливания, быстрая цель оттуда уже убежит, и точность никакой не будет.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
xmoonlight
@xmoonlight
https://sitecoder.blogspot.com
Формулу прицела меняете с пересечения двух прямых, на пересечение прямой и параболы.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы