恒定加速度运动,负加速度

时间:2020-07-25 06:21:07

标签: c# unity3d math game-physics

我在Unity上进行移动过程。

我想进行一个将物体移动到指定位置的过程,但是正如标题所示,我希望物体不仅能够移动,而且还希望其速度衰减到预定的距离。

如果加速度为负,则无法很好地处理它。 具体来说,当gif所示的初始速度为10时,我想不回头就到达一个位置。

我从恒定加速度运动公式中使用“ s = v0t + 1 / 2at ^ 2”来找到加速度“ a”,但这似乎还不够。

如果您能帮助我,我将不胜感激。

public class Test : MonoBehaviour
{
    public float t;
    public float initSpd;
    public Transform t1, t2;

    IEnumerator Start()
    {
        var p = t1.position;
        while (true) {
            t1.position = p;
            var v0t = initSpd * t;
            var distance = Vector2.Distance(t1.position, t2.position);
            var direction = (t2.position - t1.position).normalized;
            var a = (2 * (distance - v0t)) / (t * t);
            var v = initSpd;
            // update
            yield return Utils.Coroutine.WhileForSeconds(t, () =>
            {
                t1.Translate(direction * v * Time.deltaTime);
                v += a * Time.deltaTime;
            });
        }
    }
}

span = 3,初始速度= 0 初速度=0 跨度= 3,初始速度= 3 画像の説明をここに入力 跨度= 3,初始速度= 10 画像の説明をここに入力

enter image description here

2 个答案:

答案 0 :(得分:1)

您用来计算s = b t^2 + c t + d 的数学是正确的,但是您以无法解决的方式提出了问题。

正如您所说,位置恒定是时间的二次函数,因此用

b, c, d

对于某些常量dc的值已由初始位置固定。 s(finalTime) = goalPosition的值已经由初始速度确定。仅剩一个自由参数,当您求解 minimize: integral(acceleration(t)^2) from t = 0 to T subject to: x(0) given v(0) given x(T) given x(t) <= x(T) for all t in [0, T] (assuming x(0) < x(T)) 时,您将无法控制所产生的抛物线是否超过了目标。

您可以增加多项式的度数,但是总会有一些初始速度过大而导致过冲。

从本质上讲,您有一个最佳的控制/轨迹优化问题,例如

a = kp * vectorToGoal - kd * velocityVector,

正如您所说的那样,没有优化目标,但是您需要加速方面的成本或约束,否则您将获得无限加速的解决方案(例如,在第一步中非常困难地加速,然后滑行到恒定速度的目标)。

不平等使事情变得复杂。如果您想要一个连续时间的分析解决方案,那么庞特里亚金的原理将是一个解决之道,但是可能会有更简单的技巧。如果您离散化时间并使加速度为分段常数,那么这是一个容易凸的优化问题。

如果您愿意放宽“永不超调”和“恰好在此时到达”约束,那么非常简单的解决方案将使用诸如PD控制器:

kp

其中kdkp是手动调整的正常数,并且此表达式在每一帧中都将重新评估。您可以调整kd和{{1}}来最大程度地减少典型情况下的过冲。

或者,您可以做大多数游戏所要做的-允许速度瞬时变化:)

答案 1 :(得分:0)

我发现通过两步更改速度可以实现理想的行为。

    IEnumerator Start()
    {
        var p = t1.position;
        while (true)
        {
            t1.position = p;
            var direction = (t2.position - t1.position).normalized;
            var distance = Vector2.Distance(t1.position, t2.position);

            var v0 = initSpd;
            var M = distance;
            var T = duration;
            var tm = M / v0;
            var vm = v0 / T * tm;
            var accel1 = (vm - v0) / (tm - 0);
            var accel2 = (0 - vm) / (T - tm);
            Debug.Log($"vo={v0}, M={M}, T={T}, tm={tm}, vm={vm}, accel1={accel1}, accel2={accel2}");
            var v = initSpd;
            var stime = Time.time;
            var hist = 0f;
            // update
            yield return Utils.Coroutine.WhileForSeconds(T, () =>
            {
                t1.Translate(direction * v * Time.deltaTime);
                hist += v * Time.deltaTime;
                if (Time.time - stime <= tm)
                    v += accel1 * Time.deltaTime;
                else
                    v += accel2 * Time.deltaTime;
            });
            Debug.Log($"elapsed={Time.time - stime}, moved distance={hist}, v={v}");
        }
    }
相关问题