Tôi đang phát triển một công cụ trực quan 3D dựa trên Unity, nhắm mục tiêu WebGL. Người dùng hiếm khi tương tác với cảnh 3D và khi anh ta chỉ thực hiện điều chỉnh máy ảnh như xoay hoặc thu phóng chế độ xem. Tôi đã tắt vSync ( QualitySettings.vSyncCount
) và khóa tốc độ khung hình xuống 30 ( Application.targetFrameRate
) để giảm mức sử dụng CPU ít nhất một chút trong khi vẫn có mức độ phản hồi chấp nhận được khi người dùng di chuyển camera xung quanh. Với 30 khung hình / giây, tôi nhận được mức sử dụng CPU khoảng 30%. Xem xét phần cứng cấp thấp hơn có vẻ như vẫn còn quá cao.
Để giảm thêm mức sử dụng CPU, tôi đã giới thiệu hai 'chế độ':
- Tương tác: chạy với 30 khung hình / giây
- Nhàn rỗi: chạy với 10 khung hình / giây
Tôi đã viết một số dòng mã để chuyển giữa các chế độ đó tùy thuộc vào tương tác của người dùng. Vì vậy, khi một đầu vào được phát hiện, ứng dụng sử dụng nhiều khung hình / giây hơn và sau một khoảng thời gian nhất định mà không có bất kỳ tương tác nào, ứng dụng sử dụng lại ít khung hình / giây hơn. Nó hoạt động khá tốt cho đến nay: Ứng dụng sử dụng 30% ở chế độ tương tác và 8% đến 10% CPU khi ở chế độ không tải.
Đặt tốc độ khung hình nhàn rỗi thành 1, mức sử dụng CPU giảm xuống 1,5% khi ở chế độ không tải. Điều này thực sự tuyệt vời. Nhưng như dự đoán, có một vấn đề. Về cơ bản tôi đã khóa tất cả các Update()
phương thức chỉ được gọi một lần mỗi giây. Khi người dùng tương tác với máy ảnh, sự kiện sẽ được xử lý với độ trễ dự kiến là khoảng một giây.
Bây giờ câu hỏi: Làm thế nào tôi có thể phát hiện đầu vào của người dùng ngay lập tức trong khi ứng dụng chạy với tốc độ khung hình thấp và cũng ngay lập tức áp dụng tốc độ khung hình mới (giả sử 30) mà không có bất kỳ độ trễ đáng chú ý nào?
Ban đầu tôi muốn có một số loại kết xuất theo yêu cầu. Tôi đã đọc một số bài viết về cách mọi người kết xuất thành một kết cấu để giảm chi phí kết xuất trong các cảnh ít tương tác hơn. Nhưng theo tôi, việc thiết lập tốc độ khung hình có vẻ như là một giải pháp sạch hơn. Tôi cũng đã thử sử dụng FixedUpdate()
phương pháp để kiểm tra đầu vào và chuyển sang chế độ tương tác, nhưng nó cũng không hoạt động.
Lưu ý Cũng đáng đề cập, cách tiếp cận này tạo ra lỗi trong trình duyệt, chỉ ra rằng tốc độ khung hình của ứng dụng phải là 0 (không phải về tốc độ khung hình mục tiêu của Unity mà như trong 'hãy để trình duyệt xử lý tốc độ khung hình' ). Mặc dù đây có thể là một câu hỏi khác nhưng nó vẫn liên quan đến chủ đề này. Có lẽ ai đó cũng có câu trả lời cho điều đó!
Chỉnh sửa 1
Như đã đề cập trong các bình luận bên dưới, Unity cung cấp các cuộc gọi lại MonoBehaviour.OnApplicationPause
và MonoBehaviour.OnApplicationFocus
để phát hiện xem ứng dụng sắp nhận hay mất tập trung.
Tuy nhiên, vấn đề là thế này: Ứng dụng của tôi gần như không bao giờ mất tập trung. Mặc dù đây là một tối ưu hóa bổ sung tốt đẹp nhưng nó không thực sự giúp tôi quá nhiều. Vấn đề của tôi là ứng dụng nhàn rỗi hầu hết thời gian trong khi cũng có trọng tâm. Nó thực sự chỉ là người dùng nhìn chằm chằm vào cửa sổ hầu hết thời gian.
Chỉ để làm cho một số ý nghĩa hơn: Tôi đang nhắm mục tiêu WebGL. Mục đích duy nhất của Unity là trực quan hóa một số nội dung trong khi người dùng chủ yếu tương tác với một số điều khiển HTML. Trong trường hợp hiếm hoi anh ấy muốn tương tác với cảnh 3D, tôi muốn đặt tốc độ khung hình thành 30. Ý tưởng là "Tôi không tái hiện cảnh quá thường xuyên miễn là bạn không tương tác" .
Để nhấn mạnh: Trong trường hợp sử dụng phù hợp nhất của tôi, ứng dụng không bao giờ mất tập trung. Điều này có nghĩa, chỉ báo đáng tin cậy duy nhất để xác định thời điểm chuyển đổi giữa các cấu hình tốc độ khung hình được dựa trên đầu vào của người dùng.
Xin lỗi nếu tôi không quá rõ về điều đó :)
Chỉnh sửa 2
Tôi đã đăng chủ đề này trên trang Phản hồi Unity . Nếu bạn quan tâm, hãy kiểm tra và bỏ phiếu. Có lẽ yêu cầu này nhận được đủ sự chú ý để được hỗ trợ bởi các nhà phát triển Unity.