मुझे अलग-अलग आकार और वेग की वस्तुओं का एक गुच्छा मिला है जो एक दूसरे की ओर बढ़ते हैं। हर अपडेट पर, मुझे हर ऑब्जेक्ट पर जाना है और हर दूसरे ऑब्जेक्ट के गुरुत्वाकर्षण के कारण बलों को जोड़ना है। यह बहुत अच्छी तरह से पैमाने पर नहीं है, दो बड़े बाधाओं में से एक है जो मैंने अपने खेल में पाया है, और मुझे यकीन नहीं है कि प्रदर्शन में सुधार करने के लिए क्या करना चाहिए।
ऐसा लगता है कि मुझे प्रदर्शन में सुधार करने में सक्षम होना चाहिए। किसी भी समय, सिस्टम में 99% ऑब्जेक्ट्स का केवल एक वस्तु पर एक नगण्य प्रभाव होगा। मैं निश्चित रूप से वस्तुओं को द्रव्यमान द्वारा नहीं छांट सकता और केवल शीर्ष 10 सबसे बड़ी वस्तुओं या कुछ पर विचार कर सकता हूं, क्योंकि बल द्रव्यमान के साथ दूरी से अधिक भिन्न होता है (समीकरण लाइनों के साथ होता है force = mass1 * mass2 / distance^2
)। मुझे लगता है कि दुनिया की दूसरी ओर चट्टान के सैकड़ों छोटे टुकड़ों को अनदेखा करने वाली सबसे बड़ी वस्तुओं और निकटतम वस्तुओं पर विचार करने के लिए एक अच्छा अनुमान होगा , जो संभवतः कुछ भी प्रभावित नहीं कर सकता है - लेकिन यह पता लगाने के लिए कि कौन सी वस्तुएं हैं निकटतम मुझे सभी वस्तुओं पर पुनरावृत्त करना है, और उनकी स्थिति लगातार बदल रही है, इसलिए ऐसा नहीं है कि मैं सिर्फ एक बार कर सकता हूं।
वर्तमान में मैं कुछ ऐसा कर रहा हूं:
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);
}
(ध्यान दें कि मैंने बहुत सारे कोड हटा दिए हैं - उदाहरण के लिए टकराव परीक्षण, मैं टकराव का पता लगाने के लिए दूसरी बार वस्तुओं पर पुनरावृति नहीं करता)।
इसलिए मैं हमेशा पूरी सूची पर पुनरावृत्ति नहीं कर रहा हूं - मैं केवल पहली वस्तु के लिए ऐसा करता हूं, और हर बार वस्तु को उस बल का पता चलता है जो किसी अन्य वस्तु की ओर महसूस करता है, अन्य वस्तु को एक ही बल लगता है, इसलिए यह सिर्फ दोनों को अपडेट करता है उन्हें - और फिर उस पहले ऑब्जेक्ट को बाकी अपडेट के लिए फिर से विचार करने की आवश्यकता नहीं है।
Gravity.ForceUnderGravity(...)
और Motion.Velocity(...)
, आदि कार्यों सिर्फ XNA के सदिश गणित में बनाया का एक सा इस्तेमाल करते हैं।
जब दो ऑब्जेक्ट टकराते हैं, तो वे बड़े पैमाने पर मलबा बनाते हैं। इसे एक अलग सूची में रखा गया है और बड़े पैमाने पर पिंड अपने वेग की गणना के हिस्से के रूप में मलबे पर पुनरावृति नहीं करते हैं, लेकिन मलबे के प्रत्येक टुकड़े को बड़े पैमाने पर कणों पर चलना चाहिए।
यह अविश्वसनीय सीमाओं के पैमाने पर नहीं है। दुनिया असीमित नहीं है, इसमें एक सीमा शामिल है जो इसे पार करने वाली वस्तुओं को नष्ट कर देती है - मैं एक हजार या तो वस्तुओं को संभालने में सक्षम होना चाहता हूं, वर्तमान में खेल 200 के आसपास चोक करना शुरू कर देता है।
मैं इसे कैसे सुधार सकता हूं इस पर कोई विचार? कुछ हेयुरिस्टिक I का उपयोग लूप की लंबाई को सैकड़ों से घटाकर केवल कुछ करने के लिए किया जा सकता है? कुछ कोड जिन्हें मैं हर अपडेट से कम बार निष्पादित कर सकता हूं? जब तक यह एक सभ्य आकार की दुनिया के लिए अनुमति देने के लिए पर्याप्त तेज नहीं है, तब तक क्या मुझे इसे गुणा करना चाहिए? क्या मुझे GPU की वेग गणनाओं को बंद करने का प्रयास करना चाहिए? यदि हां, तो मैं इसे कैसे आर्किटेक्ट करूंगा? क्या मैं GPU पर स्थिर, साझा डेटा रख सकता हूं? क्या मैं GPU पर HLSL फ़ंक्शन बना सकता हूं और उन्हें मनमाने ढंग से (XNA का उपयोग करके) कॉल कर सकता हूं या क्या उन्हें ड्रा प्रक्रिया का हिस्सा बनना होगा?
G * m1 * m2 / r^2
, जहां जी को व्यवहार को मोड़ना है। (हालांकि मैं सिर्फ उन्हें एक पथ का अनुसरण नहीं कर सकता, क्योंकि उपयोगकर्ता सिस्टम को परेशान कर सकता है)