我正在使用余弦曲线对范围[0,pi]之间的对象施加力。根据我的计算,这应该给出一个速度的正弦曲线,t=pi/2
的速度应该是1.0f
然而,对于最简单的例子,我的最高速度为0.753。
现在如果这是一个浮点问题,那很好,但这是一个非常重要的错误,所以我很难接受它(如果是的话,为什么会有这么大的错误来计算这些值)。
一些代码:
// the function that gives the force to apply (totalTime = pi, maxForce = 1.0 in this example)
return ((Mathf.Cos(time * (Mathf.PI / totalTime)) * maxForce));
// the engine stores this value and in the next fixed update applies it to the rigidbody
// the mass is 1 so isn't affecting the result
engine.ApplyAccelerateForce(applyingForce * ship.rigidbody2D.mass);
更新
没有重力应用于对象,世界上没有其他对象可以与之交互,也没有拖动。我也使用RigidBody2D
,因此对象只在飞机上移动。
更新2
好的尝试了一个非常简单的例子,我得到了我期待的结果,所以我的代码中必定有一些东西。一旦我发现了不同的东西,我会更新。
为了记录,超级简单的代码:
float forceThisFrame;
float startTime;
// Use this for initialization
void Start () {
forceThisFrame = 0.0f;
startTime = Time.fixedTime;
}
// Update is called once per frame
void Update () {
float time = Time.fixedTime - startTime;
if(time <= Mathf.PI)
{
forceThisFrame = Mathf.Cos (time);
if(time >= (Mathf.PI /2.0f)- 0.01f && time <= (Mathf.PI /2.0f) + 0.01f)
{
print ("Speed: " + rigidbody2D.velocity);
}
}
else
{
forceThisFrame = 0.0f;
}
}
void FixedUpdate()
{
rigidbody2D.AddForce(forceThisFrame * Vector2.up);
}
更新3
我已经更改了我的原始代码以匹配上面的示例尽可能接近(下面列出的其余差异)并且仍然存在差异。
这里are my results of velocity against time。它们都不会对我有意义,使用1N的恒定力,这应该导致线性速度函数v(t) = t
,但这不是任何一个例子产生的。
剩余差异:
除此之外,我看不出任何差异,我当然也看不出为什么会有这些影响。它们都在每次固定更新时对对象施加1的力。
答案 0 :(得分:2)
对于余弦情况,这不是一个浮点问题,本身就是一个集成问题。
[在你的'固定'加速情况下,显然也存在轻微的浮点问题。)
显然,加速度与力成正比( F = ma
),但你不能简单地添加加速度来获得速度,特别是如果帧之间的时间间隔不恒定。 / p>
通过假设帧间加速度不变来简化事情,因此遵循 v = u + at
(或者 ∂v = a.∂t
),你需要缩放加速度的效果与自最后一帧以来经过的时间成比例。因此,较小的 ∂t
,您的整合就越准确。
答案 1 :(得分:0)
这是一个多部分问题,首先我没有完全理解Unity中的Update
与FixedUpdate
,有关该部分的更多信息,请参阅this question on GameDev.SE。
我的“修复”就是推进了一个带有固定更新的计时器,以便不会施加错误的力量。正如Eric Postpischil所证明的那样,问题是因为FixedUpdate
,尽管它的名字,并不是每0.02s调用一次,而是最多每0.02s调用一次。对此的修复是,在我的更新中,将一些缩放应用于强制应用以适应错过的固定更新。我的代码最终看起来像:
从更新中调用
float oldTime = time;
time = Time.fixedTime - startTime;
float variableFixedDeltaTime = time - oldTime;
float fixedRatio = variableFixedDeltaTime / Time.fixedDeltaTime;
if(time <= totalTime)
{
applyingForce = forceFunction.GetValue(time) * fixedRatio;
Vector2 currentVelocity = ship.rigidbody2D.velocity;
Vector2 direction = new Vector2(ship.transform.right.x, ship.transform.right.y);
float velocityAlongDir = Vector2.Dot(currentVelocity, direction);
float velocityPrediction = velocityAlongDir + (applyingForce * lDeltaTime);
if(time > 0.0f && // we are not interested if we are just starting
((velocityPrediction < 0.0f && velocityAlongDir > 0.0f ) ||
(velocityPrediction > 0.0f && velocityAlongDir < 0.0f ) ))
{
float ratio = Mathf.Abs((velocityAlongDir / (applyingForce * lDeltaTime)));
applyingForce = applyingForce * ratio;
// We have reversed the direction so we must have arrived
Deactivate();
}
engine.ApplyAccelerateForce(applyingForce);
}
ApplyAccelerateForce
在哪里:
public void ApplyAccelerateForce(float requestedForce)
{
forceToApply += requestedForce;
}
从FixedUpdate调用
rigidbody2D.AddForce(forceToApply * new Vector2(transform.right.x, transform.right.y));
forceToApply = 0.0f;