Очень неплохо, хороший приблизительный метод. Но на самом деле можно вполне сделать и реальную симуляцию, благо для современных компьютеров эта физика просто ерунда.
Итак, в простом случае импульсной физики объект летит так Vector3 velocity; // у него есть скорость void Update() { velocity = velocity + gravityVector * Time.delta; // каждый кадр к скорости прибавляются все внешние силы, в простом случае - гравитация (вектор вниз) transform.position = transform.position + velocity * Time.delta; // полученная скорость приращивается к позиции. }
По сути все в соответствии с физикой равноускоренного движения Для полного полета стрелы можно использовать вот такую формулу (будет работать прямо с Vector3) endPoint = startPoint + startVelocity * time + (gravityVector * time * time) / 2; Тут есть 2 неизвестных - время и начальная скорость. Они зависимые, можно зафигячить стрелу по навесной траектории вверх и она будет лететь медленнее, а можно - с большой скоростью прямой наводкой. Для фейковой величины стоит просто выбрать время, пропорциональное дистанции от балды (то есть руками подобрать, чтобы красиво выглядело). Аналогично гравитацию - подобрать по масштабу. Зная эти 2 величины (время полета и гравитационный вектор) - можно найти стартовую скорость. Два других значения есть - это позиция лучника и цели: startVelocity = (endPoint - startPoint - (gravityVector * fullTime * fullTime) / 2) / fullTime;
В итоге можно использовать вот такую формулу для нахождения фейковой траектории полета стрелы (так как и лучник и цель прямо в формуле, то при изменении их положения стрелы тоже будут чуть докручивать траекторию, как и в вашем случае)
arrowPoint = startPoint + (endPoint - startPoint - (gravityVector * fullTime * fullTime) / 2) / fullTime) * time + (gravityVector * time * time) / 2; Где fullTime - подобранное время полета, а просто time - время от старта выстрела.
Спасибо за столь развернутый ответ, я о подобном подходе к реализации не задумывался. Однако с использованием физики необходимо подбирать время полёта, а в моём случае дистанции выстрела в начале и конце уровня сильно отличаются. Тут либо подбирать такое время, чтобы на любой дистанции выглядело приемлемо, либо привязывать время полёта к общей дистанции. Кривые Безье, в свою очередь, вообще не привязаны к времени полёта, правда, если захочешь, чтобы всегда была крутая траектория (даже на большой дистанции выстрела), нужно подвязывать высоту вспомогательной точки к общей дистанции. Ну а насчет оптимизации полностью согласен - для того, чтобы увидеть весомую разницу в потребляемых ресурсах необходимо задействовать ОЧЕНЬ много подобных симуляций одновременно. Тем не менее две одновременно работающих функции интерполяции прямолинейного движения + LookRotation будут всегда шустрее работать, чем любые физические расчеты.
Для тех, кто решит использовать эту формулу в unity может быть неочевидно, как поделить вектор на число - это нужно сделать через умножение на обратное число Vector3 / float == Vector3 * (1f / float)
Очень неплохо, хороший приблизительный метод.
Но на самом деле можно вполне сделать и реальную симуляцию, благо для современных компьютеров эта физика просто ерунда.
Итак, в простом случае импульсной физики объект летит так
Vector3 velocity; // у него есть скорость
void Update() {
velocity = velocity + gravityVector * Time.delta; // каждый кадр к скорости прибавляются все внешние силы, в простом случае - гравитация (вектор вниз)
transform.position = transform.position + velocity * Time.delta; // полученная скорость приращивается к позиции.
}
По сути все в соответствии с физикой равноускоренного движения
Для полного полета стрелы можно использовать вот такую формулу (будет работать прямо с Vector3)
endPoint = startPoint + startVelocity * time + (gravityVector * time * time) / 2;
Тут есть 2 неизвестных - время и начальная скорость. Они зависимые, можно зафигячить стрелу по навесной траектории вверх и она будет лететь медленнее, а можно - с большой скоростью прямой наводкой. Для фейковой величины стоит просто выбрать время, пропорциональное дистанции от балды (то есть руками подобрать, чтобы красиво выглядело). Аналогично гравитацию - подобрать по масштабу. Зная эти 2 величины (время полета и гравитационный вектор) - можно найти стартовую скорость. Два других значения есть - это позиция лучника и цели:
startVelocity = (endPoint - startPoint - (gravityVector * fullTime * fullTime) / 2) / fullTime;
В итоге можно использовать вот такую формулу для нахождения фейковой траектории полета стрелы (так как и лучник и цель прямо в формуле, то при изменении их положения стрелы тоже будут чуть докручивать траекторию, как и в вашем случае)
arrowPoint = startPoint + (endPoint - startPoint - (gravityVector * fullTime * fullTime) / 2) / fullTime) * time + (gravityVector * time * time) / 2;
Где fullTime - подобранное время полета, а просто time - время от старта выстрела.
Спасибо за столь развернутый ответ, я о подобном подходе к реализации не задумывался. Однако с использованием физики необходимо подбирать время полёта, а в моём случае дистанции выстрела в начале и конце уровня сильно отличаются. Тут либо подбирать такое время, чтобы на любой дистанции выглядело приемлемо, либо привязывать время полёта к общей дистанции. Кривые Безье, в свою очередь, вообще не привязаны к времени полёта, правда, если захочешь, чтобы всегда была крутая траектория (даже на большой дистанции выстрела), нужно подвязывать высоту вспомогательной точки к общей дистанции. Ну а насчет оптимизации полностью согласен - для того, чтобы увидеть весомую разницу в потребляемых ресурсах необходимо задействовать ОЧЕНЬ много подобных симуляций одновременно. Тем не менее две одновременно работающих функции интерполяции прямолинейного движения + LookRotation будут всегда шустрее работать, чем любые физические расчеты.
🎮 [Velocity Ultra](https://rawg.io/games/velocity-ultra)
Дата релиза: 15.05.2013
Разработчики: Curve Digital, FuturLab
Издатель: Curve Digital
🛒 [PlayStation Store](https://store.playstation.com/en-us/product/UP4395-NPUB31396_00-VELOCITYULTRA000) • [Steam](http://store.steampowered.com/app/244890/)
Для тех, кто решит использовать эту формулу в unity может быть неочевидно, как поделить вектор на число - это нужно сделать через умножение на обратное число
Vector3 / float == Vector3 * (1f / float)