Формулы для движения по окружности и винтовой линии с переменным ускорением
Знает кто формулы для движения по окружности и винтовой линии с переменным ускорением? Не могу в инете ничего найти, а в вузе нет нужной формулы в учебнике. В идеале это реализовать в скрипте, но формулы будет достаточно. Вот код с примером движения с постоянным ускорением
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Utils;
public class AccelerationPermanent : MonoBehaviour
{
[Header("Настройки")]
[Tooltip("Ускорение")]
[SerializeField] private float _acceleration = 0;
[Tooltip("Скорость")]
[SerializeField] private float _velocity = 0;
[Tooltip("Время начала движения")]
[SerializeField] private float _timeToStartSpinning;
[Tooltip("Время таймера")]
[SerializeField] private float _time = 10;
[Tooltip("Объект вокруг которого движется таймер")]
[SerializeField] private Transform _target;
private float _radius;
private float _timePassed;
private float _accelerationLinear;
private float _velocityLinear; // разложение результирующей скорости
private const float PI = 3.14f;
private bool _t1 = true;
void Start()
{
_radius = Vector3.Distance(_target.position, transform.position);
_accelerationLinear = _acceleration / Mathf.Sqrt(2);
_velocityLinear = _velocity / Mathf.Sqrt(2);
}
void FixedUpdate()
{
if (Timer.IsTimerOff(ref _timeToStartSpinning) && _t1)
{
_t1 = false;
}
if (!_t1)
{
Move();
if (Timer.IsTimeOver(ref _time)) // Каждый промежуток времени выводим пройденное расстояние
{
float S = 0;
if (_acceleration * _velocity > 0)
S = _velocity * _timePassed +
_acceleration * _timePassed * _timePassed / 2;
else if (_acceleration == 0)
{
S = Mathf.Abs(_velocity) * _timePassed;
}
else if(_acceleration == 0 && _velocity == 0)
{
S = 0;
}
else
S = (Mathf.Abs(_velocity * _velocity) / Mathf.Abs(2 * _acceleration))
+ Mathf.Abs(_acceleration) * (_timePassed - Mathf.Abs(_velocity)
/ Mathf.Abs(_acceleration)) * (_timePassed - Mathf.Abs(_velocity) / Mathf.Abs(_acceleration)) / 2;
Debug.Log($"S = {S}, position = {transform.position}, time = {_timePassed}");
Time.timeScale = 0;
}
}
}
private void Move()
{
if (_velocity == 0 && _acceleration == 0)
return;
_timePassed += Time.fixedDeltaTime;
var height = 2 * PI * _radius;
var x = _radius * Mathf.Cos((_velocityLinear / _radius) * _timePassed + _accelerationLinear * _timePassed * _timePassed / (2 * _radius));
var y = (height / (2 * Mathf.PI)) * ((_velocityLinear / _radius) * _timePassed + _accelerationLinear * _timePassed * _timePassed / (2 * _radius));
var z = _radius * Mathf.Sin((_velocityLinear / _radius) * _timePassed + _accelerationLinear * _timePassed * _timePassed / (2 * _radius));
transform.position = new Vector3(x, y, z);
}
}
Была мысль просто каждый фрейм пересчитывать ускорение, но не уверен что это так работает.
Ответы (2 шт):
Движение по спирали это движение по окружности с смещением по третей оси! Движение по окружности можешь в школьном учебнике за 9 класс, если не ошибаюсь.
x: Cos(radian)
y: Sin(radian)
- зачем тебе
_target, если можно просто сделать объект дочерним к нему и менять локальную позицию? - почему
FixedUpdateесли ты тут не работаешь с физикой тел?
Движение по окружности и смещение это соответственно две разные скорости. Менять их можно тупо установив общий коэффициент скорости SpeedMultiplayer.
public class SpiralMovement : MonoBehaviour
{
public float SpeedMultiplayer = 1;
[SerializeField] private float _angularSpeed = 180;
[SerializeField] private float _offsetSpeed = -0.5f;
[Space]
[SerializeField] private float _radius = 1;
private float _currentRadian;
private float _currentOffset;
private void Update ()
{
float delta = Time.deltaTime*SpeedMultiplayer;
_currentRadian += _angularSpeed*Mathf.Deg2Rad*delta;
_currentOffset += _offsetSpeed*delta;
transform.localPosition = new Vector3(Mathf.Cos(_currentRadian), _currentOffset, Mathf.Sin(_currentRadian));
}
}
Меняем
Вот решение. Мб кому пригодится.
``
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Utils;
public class AccelerationChangable : MonoBehaviour
{
[Header("Настройки")]
[Tooltip("Коэффициент A")]
[SerializeField] private float _A = 0;
[Tooltip("Коэффициент B")]
[SerializeField] private float _B = 0;
[Tooltip("Скорость")]
[SerializeField] private float _velocity = 0;
[Tooltip("Время начала движения")]
[SerializeField] private float _timeToStartSpinning;
[Tooltip("Время таймера")]
[SerializeField] private float _time = 10;
[Tooltip("Объект вокруг которого движется таймер")]
[SerializeField] private Transform _target;
private float _radius;
private float _timePassed;
private float _acceleration;
private float _accelerationLinear;
private float _velocityLinear; // разложение результирующей скорости
private const float PI = 3.14f;
private bool _t1 = true;
private float _distance;
void Start()
{
_radius = Vector3.Distance(_target.position, transform.position);
_velocityLinear = _velocity / Mathf.Sqrt(2);
_acceleration = _A + _B * _timePassed;
}
void FixedUpdate()
{
if (Timer.IsTimerOff(ref _timeToStartSpinning) && _t1)
{
_t1 = false;
}
if (!_t1)
{
Move();
if (Timer.IsTimeOver(ref _time)) // Каждый промежуток времени выводим пройденное расстояние
{
float S = 0;
Debug.Log($"S = {_distance}, position = {transform.position}, time = {_timePassed}");
Time.timeScale = 0;
}
}
}
private void Move()
{
if (_velocity == 0 && _acceleration == 0)
return;
_timePassed += Time.fixedDeltaTime;
var height = 2 * PI * _radius;
var x = _radius * Mathf.Cos((_velocityLinear * _timePassed + (Mathf.Sqrt(2) / 4) * _A * _timePassed * _timePassed + (Mathf.Sqrt(2) / 12) * _B * _timePassed * _timePassed * _timePassed) * 2 * Mathf.PI / height);
var y = _velocityLinear * _timePassed + (Mathf.Sqrt(2) / 4) * _A * _timePassed * _timePassed + (Mathf.Sqrt(2) / 12) * _B * _timePassed * _timePassed * _timePassed;
var z = _radius * Mathf.Sin((_velocityLinear * _timePassed + (Mathf.Sqrt(2) / 4) * _A * _timePassed * _timePassed + (Mathf.Sqrt(2) / 12) * _B * _timePassed * _timePassed * _timePassed) * 2 * Mathf.PI / height);
_distance += Vector3.Distance(transform.position, new Vector3(x, y, z));
transform.position = new Vector3(x, y, z);
}
}
``