ฉันค้นหาคำตอบแล้ว แต่ฉันไม่สามารถหาวิธีที่ดีที่สุดในการจัดการฟังก์ชั่น / การคำนวณราคาแพง
ในเกมปัจจุบันของฉัน (อาคารเมืองแบบกระเบื้อง 2d) ผู้ใช้สามารถวางอาคารสร้างถนน ฯลฯ อาคารทุกหลังจำเป็นต้องเชื่อมต่อกับทางแยกที่ผู้ใช้ต้องวางไว้ที่ชายแดนของแผนที่ หากอาคารไม่ได้เชื่อมต่อกับทางแยกนี้สัญญาณ "ไม่ได้เชื่อมต่อกับถนน" จะปรากฏขึ้นเหนือสิ่งปลูกสร้างที่ได้รับผลกระทบ อาคารส่วนใหญ่มีรัศมีและอาจเกี่ยวข้องกันเช่นกัน (เช่นแผนกดับเพลิงสามารถช่วยบ้านทั้งหมดภายในรัศมี 30 แผ่น) นั่นคือสิ่งที่ฉันต้องปรับปรุง / ตรวจสอบเมื่อการเชื่อมต่อถนนเปลี่ยนไป
เมื่อวานนี้ฉันพบปัญหาเรื่องประสิทธิภาพที่ยิ่งใหญ่ ให้ดูสถานการณ์ต่อไปนี้: ผู้ใช้สามารถลบสิ่งปลูกสร้างและถนนได้เช่นกัน ดังนั้นหากผู้ใช้ในขณะนี้แบ่งการเชื่อมต่อทันทีหลังจากสนธิฉันจำเป็นต้องปรับปรุงอาคารจำนวนมากในเวลาเดียวกัน ฉันคิดว่าหนึ่งในคำแนะนำแรกคือการหลีกเลี่ยงการซ้อนกันลูป (ซึ่งแน่นอนเป็นเหตุผลใหญ่ในสถานการณ์นี้) แต่ฉันต้องตรวจสอบ ...
- หากอาคารยังคงเชื่อมต่อกับทางแยกในกรณีที่มีการถอดกระเบื้องถนน (ฉันทำเช่นนั้นเฉพาะอาคารที่ได้รับผลกระทบจากถนนนั้น) (อาจเป็นปัญหาที่เล็กกว่าในสถานการณ์นี้)
รายการของกระเบื้องรัศมีและได้รับอาคารภายในรัศมี(ลูปซ้อนกัน - ปัญหาใหญ่!)
// Go through all buildings affected by erasing this road tile. foreach(var affectedBuilding in affectedBuildings) { // Get buildings within radius. foreach(var radiusTile in affectedBuilding.RadiusTiles) { // Get all buildings on Map within this radius (which is technially another foreach). var buildingsInRadius = TileMap.Buildings.Where(b => b.TileIndex == radiusTile.TileIndex); // Do stuff. } }
ทั้งหมดนี้แบ่ง FPS ของฉันจาก 60 เป็นเกือบ 10 เป็นเวลาหนึ่งวินาที
ดังนั้นฉันจะทำ ความคิดของฉันจะเป็น:
- ไม่ได้ใช้เธรดหลัก (ฟังก์ชันอัปเดต) สำหรับเธรดนี้ แต่เป็นเธรดอื่น ฉันอาจพบปัญหาการล็อคเมื่อฉันเริ่มใช้มัลติเธรด
- การใช้คิวเพื่อจัดการกับการคำนวณจำนวนมาก (กรณีใดจะเป็นวิธีที่ดีที่สุดในกรณีนี้)
- เก็บข้อมูลเพิ่มเติมในวัตถุ (อาคาร) ของฉันเพื่อหลีกเลี่ยงการคำนวณเพิ่มเติม (เช่นอาคารในรัศมี)
ใช้วิธีการสุดท้ายฉันสามารถลบหนึ่งซ้อนในรูปแบบ foreach นี้แทน:
// Go through all buildings affected by erasing this road tile.
foreach(var affectedBuilding in affectedBuildings) {
// Go through buildings within radius.
foreach(var buildingInRadius in affectedBuilding.BuildingsInRadius) {
// Do stuff.
}
}
แต่ฉันไม่รู้ว่านี่เพียงพอหรือไม่ เกมอย่าง Cities Skylines จะต้องจัดการกับสิ่งก่อสร้างมากมายหากผู้เล่นมีแผนที่ขนาดใหญ่ พวกเขาจัดการกับสิ่งเหล่านั้นได้อย่างไร! อาจมีคิวการอัปเดตเนื่องจากสิ่งปลูกสร้างทั้งหมดจะไม่อัพเดตในเวลาเดียวกัน
ฉันรอคอยที่จะความคิดและความคิดเห็นของคุณ!
ขอบคุณมาก!