Tốc độ khung hình động trong Unity


8

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.OnApplicationPauseMonoBehaviour.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.


1
Bạn chỉ có thể bọc mã Cập nhật của mình bên trong khối tập trung vào ứng dụng. Có bất kỳ lý do để chạy mã Cập nhật của bạn khi ứng dụng của bạn không tập trung không? docs.unity3d.com/ScriptReference/
John Hamilton

1
@ John Johnilton Cảm ơn lời khuyên của bạn! Đó là một tối ưu hóa khác đáng thực hiện. Tuy nhiên, tôi hy vọng ứng dụng sẽ tập trung hầu hết thời gian. Vì vậy, tôi chủ yếu quan tâm đến việc giảm thiểu khối lượng công việc CPU trong khi ứng dụng đang chạy.
qCring

Chỉ cần sử dụng tạm dừng mất tập trung và tiếp tục tập trung, nên tương đối dễ thực hiện. Đăng cách thức triển khai tính năng này (dưới dạng câu trả lời) tại đây để có thể sử dụng trong tương lai :)
John Hamilton

Câu trả lời:


7

Tôi nghĩ kết xuất để kết cấu vẫn là đặt cược tốt nhất của bạn. Nếu bạn chụp "ảnh chụp màn hình" những gì máy ảnh nhìn thấy và chỉ hiển thị kết cấu đó, chi phí kết xuất sẽ rẻ ngay cả ở 30 khung hình / giây.


Cảm ơn, tôi sẽ thử điều này khi tôi chắc chắn rằng việc điều chỉnh tốc độ khung hình một cách linh hoạt sẽ dẫn đến ngõ cụt. Nhưng bạn có thể đúng mặc dù. Cách tiếp cận này xuất hiện trên nhiều diễn đàn vì vậy nó dường như là cách để đi.
qCring

1

Vì vậy, tôi đã nghĩ về điều này, điều gì sẽ xảy ra nếu bạn chỉ dừng camera hiển thị lại (Không tắt camera) khi người dùng đứng yên? Bằng cách đó, bạn vẫn có thể có một cuộc gọi thường xuyên đến Updatechức năng để đầu vào của người dùng vẫn phản hồi nhưng thiết bị sẽ không có mức tiêu thụ tài nguyên cao. Sau khi tìm kiếm nhanh, tôi tìm thấy cái này . Tôi chưa thử, đó chỉ là một ý tưởng bạn có thể thử.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.