2013-12-19 56 views
4

我正在使用餘弦曲線對範圍[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

我已經改變了我原來的代碼,以上面的例子中儘可能接近我可以(在下面列出剩餘差異)匹配和我仍然得到這個差異。

Here are my results of velocity against time。它們都對我沒有意義,恆定的力量爲1N,這應該導致線性速度函數v(t) = t,但這不是兩個例子產生的結果。

剩餘差異:

  • 即「計算」的力(現在剛返回1)被通過非統一DLL運行,儘管代碼本身駐留在統一DLL中的代碼(可以解釋更多,但不能相信這是相關的!)
  • 將力施加到剛體上的行爲是一個單獨的行爲。
  • 一個是空的環境移動立方體,另一種是移動的Model3D並有一個平面附近 - 試圖用蹩腳的項目相同的代碼立方體,同樣的問題

除此之外,我看不出有什麼區別,我當然也看不出爲什麼這些東西會影響它。他們都對每個固定更新的對象施加1的力量。

+0

我假設調用療法e沒有任何障礙可以擊中,但是有重力影響物體嗎?地面/水或類似的東西是否有摩擦? –

+0

嗯耶應該提到,沒有阻力,沒有重力,我會更新:) –

+0

只是試圖啓用剛體插值和整理我的印刷品,所以可以很容易地看到最大速度,它一貫獲得〜0.9,把打印回來,我回到0.8的速度,所以可能是某種幀速率問題。 –

回答

0

這是一個多部分問題,從我不完全瞭解UpdateFixedUpdate在Unity中,有關該部分的更多信息,請參閱this question on GameDev.SE

我從那裏得到的「解決方案」是推進一個與固定更新一起進行的定時器,以便不施加錯誤的力量。正如Eric Postpischil所證明的那樣,問題在於FixedUpdate,儘管名稱不是每0.02秒就調用一次,而是最多每0.02秒調用一次。解決這個問題的方法是,在我的更新中,將一些縮放應用於要應用的部隊以適應錯過的固定更新。我的代碼最終看起來像:調用從更新

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; 
2

對於餘弦情況,這不是一個浮點問題,它本身就是一個整合問題。

[在你的'固定'加速情況下,顯然還有小浮點問題]。

顯然加速度成正比力(F = ma),但你不能只是簡單地將加速,以獲得速度,特別是當幀之間的時間間隔不是恆定的。

通過假設幀間加速度是恆定的,並且因此以下v = u + at(或交替∂v = a.∂t),則需要按比例繪製的加速度成比例地自上一幀所經過的時間的效果簡化的東西。因此,更小的∂t是,您的整合更準確。

+0

OP,您是否嘗試過使用time.deltaTime或time.smoothDeltaTime代替手寫您的時間更新代碼? – theodox

+0

@theodox當我使用Time.deltaTime時,我得到了一個[issue](http://gamedev.stackexchange.com/questions/67534/why-do-my-velocity-estimates-have-such-a-large-margin錯誤)估計我的下一個速度。我將調查smoothDeltaTime。 –

+0

這與Eric的評論一致指出了我的正確方向。問題來自FixedUpdate儘管名稱不一定以固定間隔被調用的事實。如果沒關係,我會寫出我最終做了什麼? –