2016-03-30 5 views
0

私は、プレイヤーが力を加えて動かすシンプルなゲームを作っています。しかし、私は彼の加速が一定であることを望んでいません - 私はそれを現在のスピードに応じて変えたいと思います。私はこれを行うには、単純な加速スクリプトを作ったが、それは所望の効果を達成しない:私も試した数式を使用してプレーヤーの速度を定義する

float acceleration 
{ 
    get { return speed/inversedAcceleration; } 
} 

void FixedUpdate() { 
    rb.AddForce(transform.forward * speed); 
    if (speed < maxSpeed) 
     speed += acceleration * Time.deltaTime;  
} 

新しい方法:

float timer = 1.0f; 

public float velocity { get { return Mathf.Sqrt(timer)*10; } } 

void FixedUpdate() 
{ 
    timer += Time.deltaTime; 
    rb.AddForce(transform.forward * velocity); 
} 

私が実験しているので、ロジックは、少し複雑ですそれとしばらく失敗しました。今、私は私の速度のモデルとして数式を使用するように変更する必要があると思う、私の現在のものではなく、合理的な関数のいくつかの形式です。 AddForce()を使用しながら、これを行うコードを変更するにはどうすればいいですか?プレイヤーは他のオブジェクトと物理的に正しく対話しますか?

+1

私はあなたがここでやっていることと少し混乱しています。なぜあなたは加速*質量のようなものではなく、 'AddForce()'で速度を使用していますか?なぜあなたは 'AddForce()'を独自のアクセラレーション実装と混ぜていますか?あなたのスクリプトはどのようにあなたが望むものではありませんか? – Serlite

+0

@Serlite私はそれが少し複雑であることを知っていますが、私はこのスクリプトを何度も変更してしまい、変数名が間違っています。 'speed'は開始時に設定され、' maxSpeed'に達するまで増加し、プレーヤーの実際の速度を制御しません。私は 'Addforce()'を使用しています。なぜなら、プレイヤーは何かをヒットするときにスローダウンしたいからです。 –

+0

ここで物理システムを間違って使用しているような気がします。剛体の速度のより正確な表現は 'velocity.magnitude'です。これを 'maxSpeed'と比較することで、さらに力を加えるべきかどうかを判断できます。手動で' speed'変数を追跡する必要はありません。 – Serlite

答えて

1

私が最初に提案したのは、オブジェクトの速度を手動で追跡することを避けることでした。Unityの物理システムでは、これを正確にRigidbody.velocity.magnitudeに簡単にアクセスできます。これを使用してmaxSpeedと比較して、追加の力を加えるべきかどうかを判断することができます。

速度がf(x)=sqrt(x)のカーブに一致するようにしたい場合は、このためにいくつかの基本的な計算を行う必要があります。人為的に速度を制限したくないので(物理的なやりとりを起こさせたいので)、その代わりにアクセラレーションを関数に制約する必要があります。

プレーヤーの加速度を定義する関数を決定するには、速度を(理想的には)一致させる関数を導出する必要があります。これは、指定されたポイントでの速度の変化率を与えます。これは定義上、加速です。

ここでは、理想速度のモデルとして関数f(x)=sqrt(x)を使用します。 sqrt(x)の派生は1/(2 * sqrt(x))です - これは私たちの加速を定義する関数です。ここでは、与えられた速度の加速度を決定する必要があります。これは、コード内で使用する関係であるためです。これは少し簡単な代数を取る - 私たちは、与えられたyxのために解決する必要があります

  y = 1/(2 * sqrt(x)) 
sqrt(x) * y = 1/2 
    sqrt(x) = 1/(2 * y) 
      x = (1/(2 * y))^2 

今、私たちは、任意のスピードに必要な加速を提供してくれます方程式を持っています。私たちは今、コードにこれを置くことができます - maxSpeedまでの平方根関数に従って加速:

float maxAcceleration = 10; 

// Basically x = (1/(2 * y))^2, but in code 
float CalculateAccGivenSpeed(float speed) 
{ 
    // Early exit so we don't bother with undefined results from dividing by 0 
    if (speed == 0) 
    { 
     return Mathf.Infinity; 
    } 

    float rootAcc = 1/(2 * speed); 
    return rootAcc * rootAcc; 
} 

void FixedUpdate() 
{ 
    // Only accelerate if speed is lower than maximum allowed 
    if (rb.velocity.magnitude < maxSpeed) 
    { 
     float allowableAcc = CalculateAccGivenSpeed(rb.velocity.magnitude); 

     // Constrain acceleration here so rigidbody doesn't explode from stationary 
     allowableAcc = Mathf.Min(maxAcceleration, allowableAcc); 

     // Using ForceMode.Acceleration so we don't have to worry about mass 
     rb.AddForce(transform.forward * allowableAcc, ForceMode.Acceleration); 
    } 
} 

加速度があまりにも速く/ゆっくり行くあなた見つけた場合、あなたはスカラー値でCalculateAccGivenSpeed()の結果を掛けることができます。数学的には、平方根関係を維持しながら、与えられたy値(速度)に達する速度を変えながら、平方根関数をy軸に沿ってスケーリングします。

希望すると便利です。ご質問がある場合はお知らせください。

+0

詳しいアンサーに感謝します!私はスクリプトのアイデアを理解していますが、今はテストできません。私は家に帰るとすぐに私はします。 –

+1

問題はありません - 少なくとも、私はこれがあなたを正しい方向に向けることを願っています! – Serlite

+0

私はこのスクリプトをテストしましたが、1つの問題があります。オブジェクトのドラッグを0以上に設定した場合、速度はCalculateAccGivenSpeed()の結果を何回乗算しても一定の値で停止します。例えば、ドラッグを1に設定すると、速度は約4.031で停止します。あなたはこの問題を修正するかもしれないことを知っていますか? Mayby数式を変更しますか? –

1

すべての物理式を一貫した状態に保ちたい(物理現象を再考するのは難しい)ので、ある物理学の解はオブジェクトの質量を速度の関数にすることができます(例:m=m_0+k*v^2)。

結果として、力が大きい場合(すなわち、より速く移動している場合)、力はF=maになります。

音が聞こえますか?さて、それは何ですか?E=mc^2は非常に高速に移動するオブジェクトのための手段です。しかし、私は他の相対論的効果を実装することを推奨しません。

+0

私はオブジェクトの質量を変更することは良い解決策ではないと思います。なぜなら、他のアクション(ジャンプなど)を実行し、他のすべてのアクションを実行する可能性があるからです。私は別のものを試しました(あなたはそれを見ることができます)。それが大丈夫かどうか確認できますか? –

+0

@faken、スカラー値で3dスピード/アクセラレーション/フォースをどのように実装していますか? – Matt

+0

私の質問に追加したスクリプトについてどう思いますか?それは十分な神ですか?それとも、いくつかのバグがありますか? –

関連する問題