Saya punya banyak objek dengan ukuran dan kecepatan yang bervariasi yang saling tertarik satu sama lain. Pada setiap pembaruan, saya harus membahas setiap objek dan menambahkan kekuatan karena gravitasi dari setiap objek lainnya. Ini tidak skala dengan sangat baik, adalah salah satu dari dua hambatan besar yang saya temukan dalam permainan saya, dan saya tidak yakin apa yang harus dilakukan untuk meningkatkan kinerja.
Ini terasa seperti saya harus bisa meningkatkan kinerja. Pada waktu tertentu, mungkin 99% objek dalam sistem hanya akan memiliki pengaruh yang diabaikan pada objek. Saya tentu saja tidak dapat mengurutkan objek berdasarkan massa dan hanya mempertimbangkan 10 objek terbesar atau sesuatu, karena gaya bervariasi dengan jarak lebih dari dengan massa (persamaannya adalah di sepanjang garis force = mass1 * mass2 / distance^2
). Saya pikir perkiraan yang baik adalah dengan mempertimbangkan benda - benda terbesar dan benda -benda terdekat, mengabaikan ratusan pecahan batu kecil di sisi lain dunia yang tidak mungkin mempengaruhi apa pun - tetapi untuk mengetahui benda mana yang paling dekat saya harus mengulangi semua objek, dan posisi mereka berubah terus-menerus, jadi bukan berarti saya bisa melakukannya sekali saja.
Saat ini saya sedang melakukan sesuatu seperti ini:
private void UpdateBodies(List<GravitatingObject> bodies, GameTime gameTime)
{
for (int i = 0; i < bodies.Count; i++)
{
bodies[i].Update(i);
}
}
//...
public virtual void Update(int systemIndex)
{
for (int i = systemIndex + 1; i < system.MassiveBodies.Count; i++)
{
GravitatingObject body = system.MassiveBodies[i];
Vector2 force = Gravity.ForceUnderGravity(body, this);
ForceOfGravity += force;
body.ForceOfGravity += -force;
}
Vector2 acceleration = Motion.Acceleration(ForceOfGravity, Mass);
ForceOfGravity = Vector2.Zero;
Velocity += Motion.Velocity(acceleration, elapsedTime);
Position += Motion.Position(Velocity, elapsedTime);
}
(perhatikan bahwa saya telah menghapus banyak kode - misalnya tes tabrakan, saya tidak mengulangi objek kedua kalinya untuk mendeteksi tabrakan).
Jadi saya tidak selalu mengulangi seluruh daftar - saya hanya melakukan itu untuk objek pertama, dan setiap kali objek menemukan kekuatan rasanya terhadap objek lain, objek lain merasakan kekuatan yang sama, jadi itu hanya memperbarui kedua mereka - dan kemudian objek pertama itu tidak harus dipertimbangkan lagi untuk sisa pembaruan.
Fungsi Gravity.ForceUnderGravity(...)
dan Motion.Velocity(...)
, dll. Hanya menggunakan sedikit XNA yang dibangun dalam matematika vektor.
Ketika dua benda bertabrakan, mereka menciptakan puing tanpa massa. Itu disimpan dalam daftar terpisah dan benda-benda besar tidak iterate atas puing-puing sebagai bagian dari perhitungan kecepatan mereka, tetapi setiap potongan puing harus beralih pada partikel-partikel besar.
Ini tidak harus skala ke batas luar biasa. Dunia ini tidak terbatas, mengandung perbatasan yang menghancurkan benda-benda yang melintasinya - Saya ingin dapat menangani mungkin sekitar seribu benda, saat ini permainan mulai tersedak sekitar 200.
Adakah pemikiran tentang bagaimana saya dapat meningkatkan ini? Beberapa heuristik yang bisa saya gunakan untuk mencukur panjang loop dari ratusan ke hanya beberapa? Beberapa kode saya dapat mengeksekusi lebih jarang daripada setiap pembaruan? Haruskah saya hanya multithread sampai cukup cepat untuk memungkinkan dunia berukuran layak? Haruskah saya mencoba menurunkan perhitungan kecepatan ke GPU? Jika demikian, bagaimana saya merancang itu? Bisakah saya menyimpan data statis yang dibagikan di GPU? Dapatkah saya membuat fungsi HLSL pada GPU dan memanggilnya secara sewenang-wenang (menggunakan XNA) atau apakah mereka harus menjadi bagian dari proses pengundian?
G * m1 * m2 / r^2
, di mana G hanya untuk mengubah perilaku. (walaupun saya tidak bisa membiarkan mereka mengikuti jalur, karena pengguna dapat mengganggu sistem)