Tôi đã tìm kiếm câu trả lời nhưng tôi không thể tìm ra cách tiếp cận tốt nhất để xử lý các hàm / tính toán đắt tiền.
Trong trò chơi hiện tại của tôi (tòa nhà thành phố dựa trên gạch 2d), người dùng có thể đặt các tòa nhà, xây dựng đường, v.v ... Tất cả các tòa nhà cần có kết nối với một ngã ba mà người dùng phải đặt ở biên giới của bản đồ. Nếu tòa nhà không được kết nối với ngã ba này, biển báo "Không được kết nối với đường" sẽ bật lên phía trên tòa nhà bị ảnh hưởng (nếu không phải xóa). Hầu hết các tòa nhà đều có bán kính và cũng có thể liên quan đến nhau (ví dụ: sở cứu hỏa có thể giúp tất cả các ngôi nhà trong bán kính 30 gạch). Đó là những gì tôi cũng cần cập nhật / kiểm tra khi kết nối đường bộ thay đổi.
Hôm qua tôi gặp phải một vấn đề hiệu suất lớn. Hãy xem xét kịch bản sau đây: Tất nhiên người dùng cũng có thể xóa các tòa nhà và đường. Vì vậy, nếu bây giờ người dùng ngắt kết nối ngay sau ngã ba, tôi cần cập nhật nhiều tòa nhà cùng một lúc . Tôi nghĩ một trong những lời khuyên đầu tiên là tránh các vòng lặp lồng nhau (đó chắc chắn là một lý do lớn trong kịch bản này) nhưng tôi phải kiểm tra ...
- nếu một tòa nhà vẫn được kết nối với ngã ba trong trường hợp gạch đường đã bị gỡ bỏ (tôi chỉ làm điều đó đối với các tòa nhà bị ảnh hưởng bởi con đường đó). (Có thể là một vấn đề nhỏ hơn trong kịch bản này)
danh sách các ô bán kính và nhận các tòa nhà trong bán kính (các vòng lặp lồng nhau - vấn đề lớn!) .
// 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. } }
Tất cả điều này phá vỡ FPS của tôi từ 60 đến gần 10 trong một giây.
Tôi cũng có thể làm được. Ý tưởng của tôi sẽ là:
- Không sử dụng luồng chính (Chức năng cập nhật) cho luồng này mà là luồng khác. Tôi có thể gặp vấn đề về khóa khi tôi bắt đầu sử dụng đa luồng.
- Sử dụng hàng đợi để xử lý nhiều tính toán (cách tiếp cận tốt nhất trong trường hợp này là gì?)
- Giữ thêm thông tin trong các đối tượng của tôi (các tòa nhà) để tránh tính toán nhiều hơn (ví dụ: các tòa nhà trong bán kính).
Sử dụng cách tiếp cận cuối cùng, tôi có thể loại bỏ một lồng trong mẫu foreach này thay thế:
// 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.
}
}
Nhưng tôi không biết nếu điều này là đủ. Các trò chơi như City Skylines phải xử lý nhiều tòa nhà hơn nếu người chơi có bản đồ lớn. Làm thế nào để họ xử lý những điều đó?! Có thể có một hàng đợi cập nhật vì không phải tất cả các tòa nhà đều cập nhật cùng một lúc.
Tôi đang mong chờ ý kiến và ý kiến của bạn!
Cảm ơn rất nhiều!