ฉันมีสิ่งของหลายชิ้นที่มีขนาดและความเร็วต่างกันไปซึ่งกันและกัน ในการอัพเดททุกครั้งฉันต้องข้ามวัตถุทุกอย่างและรวมแรงเข้าด้วยกันเนื่องจากแรงโน้มถ่วงของวัตถุอื่น ๆ มันไม่ได้ปรับขนาดได้ดีมากเป็นหนึ่งในสองคอขวดใหญ่ที่ฉันพบในเกมของฉันและฉันไม่แน่ใจว่าต้องทำอย่างไรเพื่อปรับปรุงประสิทธิภาพ
มันรู้สึกเหมือนฉันควรจะสามารถที่จะปรับปรุงประสิทธิภาพการทำงาน เมื่อถึงเวลาใดก็ตาม 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
มีความคิดเกี่ยวกับว่าฉันจะปรับปรุงสิ่งนี้ได้อย่างไร ฮิวริสติกบางอย่างที่ฉันสามารถใช้เพื่อโกนความยาวของลูปจากหลายร้อยไปจนถึงเพียงไม่กี่ รหัสบางอย่างที่ฉันสามารถเรียกใช้งานได้บ่อยกว่าการอัพเดททุกครั้ง? ฉันควร multithread มันจนกว่ามันจะเร็วพอที่จะทำให้โลกมีขนาดพอเหมาะ ฉันควรลองลดการคำนวณความเร็วลงสู่ GPU หรือไม่ ถ้าเป็นเช่นนั้นฉันจะออกแบบได้อย่างไร ฉันสามารถเก็บข้อมูลคงที่และใช้ร่วมกันบน GPU ได้หรือไม่? ฉันสามารถสร้างฟังก์ชั่น HLSL บน GPU และเรียกพวกมันตามอำเภอใจ (ใช้ XNA) หรือว่าพวกเขาจะต้องเป็นส่วนหนึ่งของกระบวนการวาด
G * m1 * m2 / r^2
ที่ G เป็นเพียงการปรับแต่งพฤติกรรม (แม้ว่าฉันไม่สามารถเพียงแค่มีพวกเขาไปตามเส้นทางเพราะผู้ใช้สามารถรบกวนระบบ)