Cách những con đường chậm thu hút cả người chơi trò chơi và nhà phát triển, đồng thời làm nổi bật những khả năng đáng kinh ngạc của mô hình 3D trong trình duyệt

Khám phá tiềm năng của WebGL với khung cảnh vô tận, được tạo ra theo quy trình của trò chơi lái xe thông thường này.

Đường chậm là một trò chơi lái xe thông thường tập trung vào việc tạo cảnh quay theo trình tự vô tận, tất cả đều được lưu trữ trong trình duyệt dưới dạng ứng dụng WebGL. Đối với nhiều người, việc mang đến trải nghiệm chuyên sâu như vậy dường như không phù hợp trong bối cảnh hạn chế của trình duyệt. Và thực sự, việc giải quyết vấn đề đó là một trong những mục tiêu của tôi khi thực hiện dự án này. Trong bài viết này, tôi sẽ phân tích một số kỹ thuật mà tôi đã sử dụng để vượt qua rào cản về hiệu suất trong sứ mệnh của mình nhằm làm nổi bật tiềm năng có thể bỏ qua của công nghệ 3D trên web.

Phát triển 3D trong trình duyệt

Sau khi phát hành Đường chậm, tôi thấy một nhận xét định kỳ trong phản hồi: "Tôi không biết có thể thực hiện điều này trong trình duyệt". Nếu bạn chia sẻ quan điểm này, chắc chắn bạn không phải là người thiểu số. Theo khảo sát Trạng thái JS năm 2022, có khoảng 80% nhà phát triển chưa thử nghiệm WebGL. Đối với tôi, tôi cảm thấy xấu hổ khi có thể bỏ lỡ quá nhiều tiềm năng, đặc biệt là khi nói đến trò chơi dựa trên trình duyệt. Với đường Chậm, tôi hy vọng có thể đưa WebGL hơn nữa đến với sự chú ý và có thể giúp giảm số lượng nhà phát triển chần chừ với cụm từ "công cụ phát triển trò chơi JavaScript hiệu suất cao".

WebGL có vẻ bí ẩn và phức tạp đối với nhiều người, nhưng trong những năm gần đây, các hệ sinh thái phát triển của WebGL đã dần hoàn thiện thành các công cụ và thư viện có khả năng và tiện lợi cao. Giờ đây, các nhà phát triển giao diện người dùng có thể dễ dàng tích hợp trải nghiệm người dùng 3D vào công việc, ngay cả khi chưa có kinh nghiệm về đồ hoạ máy tính. Three.js, thư viện WebGL hàng đầu, đóng vai trò là nền tảng cho nhiều bản mở rộng, bao gồm cả react-ba-fiber để đưa các thành phần 3D vào khung React. Hiện cũng có các trình chỉnh sửa trò chơi toàn diện dựa trên nền tảng web, chẳng hạn như Babylon.js hoặc PlayCanvas cung cấp một giao diện quen thuộc và các chuỗi công cụ tích hợp.

Tuy nhiên, dù những thư viện này có nhiều tiện ích, nhưng các dự án đầy tham vọng cuối cùng vẫn bị ràng buộc bởi những hạn chế về mặt kỹ thuật. Những người hoài nghi về ý tưởng chơi trò chơi dựa trên trình duyệt có thể nhấn mạnh rằng JavaScript là JavaScript đơn luồng và bị hạn chế về tài nguyên. Tuy nhiên, việc điều hướng những giới hạn này sẽ mở ra giá trị ẩn: không có nền tảng nào khác cung cấp khả năng hỗ trợ tiếp cận tức thì cũng như khả năng tương thích hàng loạt mà trình duyệt kích hoạt. Người dùng trên mọi hệ thống hỗ trợ trình duyệt đều có thể bắt đầu chơi chỉ với một cú nhấp chuột mà không cần cài đặt các ứng dụng cũng như không cần đăng nhập vào các dịch vụ. Đó là còn chưa kể đến việc các nhà phát triển vẫn thích được tận hưởng sự tiện lợi tinh tế khi có sẵn khung giao diện người dùng mạnh mẽ để xây dựng giao diện người dùng hoặc xử lý mạng cho chế độ nhiều người chơi. Theo tôi, những giá trị này chính là yếu tố làm cho trình duyệt trở thành một nền tảng tuyệt vời cho cả người chơi lẫn nhà phát triển, và như đã chứng minh qua Đường chậm, các hạn chế kỹ thuật thường có thể dẫn đến vấn đề thiết kế.

Đạt được hiệu suất trơn tru trên Đường chậm

Do các yếu tố cốt lõi của Đường chậm liên quan đến chuyển động tốc độ cao và tạo cảnh quan tốn kém, nên mọi quyết định thiết kế của tôi càng được nhấn mạnh hơn nữa. Chiến lược chính của tôi là bắt đầu bằng một thiết kế lối chơi đơn giản, cho phép thực hiện các đoạn cắt ngắn theo bối cảnh trong cấu trúc của công cụ. Mặt khác, điều này có nghĩa là đánh đổi một số tính năng cần có theo mục đích tối giản. Tuy nhiên, kết quả là sẽ tạo ra một hệ thống riêng, được tối ưu hoá và có thể chơi mượt mà trên nhiều trình duyệt và thiết bị.

Dưới đây là bảng phân tích các thành phần chính giúp duy trì đường chậm.

Xây dựng công cụ môi trường xung quanh lối chơi

Là thành phần chính của trò chơi, công cụ tạo môi trường chắc chắn sẽ tốn kém tài nguyên, có thể chỉ chiếm phần lớn ngân sách cho bộ nhớ và điện toán. Bí quyết được sử dụng ở đây là lên lịch và phân phối tác vụ tính toán nặng trong một khoảng thời gian, để không làm gián đoạn tốc độ khung hình do hiệu suất tăng đột biến.

Môi trường bao gồm các ô có hình học, khác nhau về kích thước và độ phân giải (được phân loại là "mức chi tiết" hoặc LoD) tuỳ thuộc vào khoảng cách giữa các ô đó với máy ảnh. Trong các trò chơi thông thường có máy ảnh chuyển vùng tự do, các LoD khác nhau phải liên tục được tải và huỷ tải để cung cấp chi tiết về môi trường xung quanh người chơi bất cứ nơi nào họ có thể chọn đến. Đây có thể là một thao tác tốn kém và lãng phí, đặc biệt là khi chính môi trường đó được tạo một cách linh động. Rất may là quy ước này có thể bị thay đổi hoàn toàn trong Đường chậm nhờ kỳ vọng theo bối cảnh rằng người dùng nên ở lại trên đường. Thay vào đó, bạn có thể dành riêng hình học chi tiết cao cho hành lang hẹp trực tiếp ở bên cạnh tuyến đường.

Một sơ đồ thể hiện việc tạo đường đi trước có thể cho phép chủ động lên lịch và lưu vào bộ nhớ đệm của việc tạo môi trường.
Hình ảnh môi trường trên Đường có tốc độ chậm được hiển thị dưới dạng khung dây, cho biết hành lang có hình học có độ phân giải cao bên cạnh đường. Các phần xa của môi trường, không bao giờ được nhìn thấy cận cảnh, được kết xuất ở độ phân giải thấp hơn nhiều.

Chính đường giữa được tạo ra trước khi người chơi đến, cho phép dự đoán chính xác chính xác thời điểm và vị trí cần chi tiết về môi trường. Kết quả là một hệ thống tinh gọn có thể chủ động lên lịch công việc tốn kém, chỉ tạo mức tối thiểu cần thiết tại từng thời điểm và không lãng phí công sức vào những chi tiết không nhìn thấy được. Kỹ thuật này chỉ có thể thực hiện được vì đường là một đường dẫn duy nhất, không phân nhánh. Đây là một ví dụ hay về việc đánh đổi lối chơi sao cho phù hợp với các lối cắt ngắn về mặt cấu trúc.

Một sơ đồ thể hiện việc tạo đường đi trước có thể cho phép chủ động lên lịch và lưu vào bộ nhớ đệm của việc tạo môi trường.
Bằng cách nhìn vào một khoảng cách nhất định trên đường, các phân đoạn môi trường có thể được giành trước và tạo dần ngay trước khi cần thiết. Ngoài ra, mọi phần sẽ được xem lại trong tương lai gần có thể được xác định và lưu vào bộ nhớ đệm để tránh việc tạo lại không cần thiết.

Khéo léo với các định luật vật lý

Sau nhu cầu điện toán của công cụ môi trường là hoạt động mô phỏng thực tế. Đường chậm sử dụng công cụ vật lý tối thiểu, tuỳ chỉnh để lấy mọi đoạn cắt ngắn có sẵn.

Ưu điểm chính ở đây là tránh mô phỏng quá nhiều đối tượng ngay từ đầu – dựa vào ngữ cảnh zen tối thiểu bằng cách chiết khấu những thứ như va chạm động và đối tượng có thể phá huỷ. Giả định xe vẫn chạy trên đường có nghĩa là bạn có thể bỏ qua việc va chạm với các vật thể nằm trên đường. Ngoài ra, việc mã hoá đường dưới dạng đường giữa thưa thớt còn mang đến các thủ thuật tinh tế giúp phát hiện va chạm nhanh với mặt đường và rào chắn, tất cả đều dựa trên khoảng cách kiểm tra đến tâm đường. Việc lái xe địa hình sẽ trở nên tốn kém hơn, nhưng đây là một ví dụ khác về sự đánh đổi công bằng phù hợp với bối cảnh chơi trò chơi.

Quản lý mức sử dụng bộ nhớ

Là một tài nguyên khác bị hạn chế về trình duyệt, bạn phải quản lý bộ nhớ cẩn thận, mặc dù thực tế thì JavaScript vẫn đang được thu gom rác. Việc khai báo một lượng nhỏ bộ nhớ mới trong một vòng lặp trò chơi có thể dễ dàng bị bỏ qua, nhưng việc khai báo ngay cả một lượng nhỏ bộ nhớ mới trong vòng lặp trò chơi có thể tạo ra các vấn đề nghiêm trọng khi chạy ở tốc độ 60Hz. Bên cạnh việc tiêu hao tài nguyên của người dùng trong bối cảnh họ có thể làm nhiều việc cùng lúc, việc thu gom rác lớn có thể cần một vài khung hình để hoàn tất, gây ra tình trạng gián đoạn đáng kể. Để tránh điều này, bộ nhớ vòng lặp có thể được phân bổ trước trong các biến lớp khi khởi tạo và được tái chế trong mỗi khung.

Ảnh trước và sau của hồ sơ bộ nhớ trong quá trình tối ưu hoá cơ sở mã Đường bị chậm, cho thấy mức tiết kiệm đáng kể và tốc độ thu gom rác giảm.
Mặc dù mức sử dụng bộ nhớ tổng thể hầu như không thay đổi, nhưng việc phân bổ trước và tái chế bộ nhớ vòng lặp có thể giảm đáng kể tác động của việc thu gom rác tốn kém.

Một điều cũng rất quan trọng là các cấu trúc dữ liệu nặng hơn, chẳng hạn như hình học và vùng đệm dữ liệu liên quan, được quản lý về mặt kinh tế. Trong một trò chơi được tạo ra vô hạn như Đường có tốc độ chậm, hầu hết các hình học đều tồn tại trên một loại máy chạy bộ – một khi một mảnh ghép cũ rớt lại phía sau, cấu trúc dữ liệu của nó có thể được lưu trữ và tái chế một lần nữa cho thế giới sắp tới, một mẫu thiết kế được gọi là gộp các đối tượng.

Các phương pháp này giúp ưu tiên quá trình thực thi tinh gọn, nhưng vẫn đơn giản hoá mã. Trong bối cảnh hiệu suất cao, bạn cần lưu ý đến cách các tính năng tiện lợi đôi khi mượn từ ứng dụng vì lợi ích của nhà phát triển. Ví dụ: các phương thức như Object.keys() hoặc Array.map() cực kỳ tiện dụng, nhưng bạn có thể dễ dàng bỏ qua việc mỗi phương thức sẽ tạo một mảng mới cho giá trị trả về của chúng. Việc hiểu rõ hoạt động bên trong của các hộp đen này có thể giúp bạn thắt chặt mã và tránh những va chạm về hiệu suất lén lút.

Giảm thời gian tải bằng thành phần được tạo theo quy trình

Mặc dù hiệu suất thời gian chạy là mối quan tâm chính của các nhà phát triển trò chơi, các tiên đề thông thường liên quan đến thời gian tải trang web ban đầu vẫn đúng. Người dùng có thể sẽ dễ bỏ qua hơn khi cố ý truy cập vào nội dung có dung lượng lớn, nhưng thời gian tải lâu vẫn có thể gây ảnh hưởng xấu đến trải nghiệm, nếu không giữ chân người dùng. Trò chơi thường yêu cầu các thành phần lớn ở dạng hoạ tiết, âm thanh cũng như mô hình 3D và ít nhất các thành phần này phải được nén cẩn thận ở bất cứ nơi nào có thể bỏ bớt chi tiết.

Ngoài ra, việc tạo tài sản trên máy khách theo quy trình có thể tránh được việc chuyển mất nhiều thời gian ngay từ đầu. Đây là một lợi ích rất lớn cho người dùng trên các thiết bị kết nối chậm, đồng thời giúp nhà phát triển có thêm quyền kiểm soát trực tiếp đối với cách cấu thành trò chơi, không chỉ đối với bước tải ban đầu mà còn đối với việc điều chỉnh mức độ chi tiết cho các chế độ cài đặt chất lượng khác nhau.

Một phép so sánh minh hoạ cách chất lượng của hình học được tạo theo quy trình trên Đường chậm có thể được điều chỉnh một cách linh hoạt cho phù hợp với nhu cầu về hiệu suất của người dùng.

Hầu hết hình học trong Đường chậm đều được tạo theo quy trình và đơn giản, với các chương trình đổ bóng tuỳ chỉnh kết hợp nhiều hoạ tiết để làm nổi bật chi tiết. Nhược điểm là các hoạ tiết này có thể là các thành phần nặng, mặc dù vẫn có nhiều cơ hội để tiết kiệm hơn ở đây, với các phương thức như hoạ tiết ngẫu nhiên có thể đạt được chi tiết hơn từ các hoạ tiết nguồn nhỏ. Và ở cấp độ cao nhất, bạn cũng có thể tạo kết cấu hoàn toàn trên ứng dụng bằng các công cụ như texgen.js. Điều này cũng đúng đối với âm thanh, vì Web Audio API cho phép tạo âm thanh bằng các nút âm thanh.

Với lợi ích của thành phần quy trình, việc tạo môi trường ban đầu chỉ mất trung bình 3,2 giây. Để tận dụng tối đa kích thước tải xuống phía trước nhỏ, màn hình chờ đơn giản sẽ chào đón khách truy cập mới và trì hoãn việc khởi chạy cảnh đắt tiền cho đến khi nhấn nút xác nhận. Việc này cũng đóng vai trò là vùng đệm thuận tiện cho các phiên bị thoát, giảm thiểu việc chuyển một cách lãng phí tài sản tải động.

Biểu đồ thời gian tải cho thấy đỉnh điểm mạnh trong 3 giây đầu tiên chiếm hơn 60% số người dùng, sau đó là giảm nhanh chóng. Biểu đồ này cho thấy hơn 97% người dùng thấy thời gian tải dưới 10 giây.

Áp dụng phương pháp linh hoạt đối với tình trạng tối ưu hoá trễ

Tôi luôn coi cơ sở mã cho Đường chậm là mang tính thử nghiệm và do đó, chúng tôi đã thực hiện một phương pháp phát triển cực kỳ nhanh chóng. Khi làm việc với một cấu trúc hệ thống phức tạp và phát triển nhanh chóng, có thể khó dự đoán nơi nút thắt cổ chai quan trọng có thể xảy ra. Trọng tâm nên là triển khai các tính năng mong muốn một cách nhanh chóng, thay vì chỉn chu, sau đó triển khai ngược lại để tối ưu hoá các hệ thống thực sự quan trọng. Trình phân tích hiệu suất trong Công cụ của Chrome cho nhà phát triển là vô giá đối với bước này và đã giúp tôi chẩn đoán một số vấn đề lớn xảy ra với các phiên bản trước đây của trò chơi. Với vai trò là nhà phát triển, bạn đã dành thời gian quý báu, vì vậy, hãy đảm bảo bạn không dành thời gian để cân nhắc về các vấn đề có thể là không đáng kể hoặc dư thừa.

Giám sát trải nghiệm người dùng

Trong khi triển khai tất cả các thủ thuật này, điều quan trọng là phải đảm bảo trò chơi hoạt động như mong đợi ngoài điều kiện thực tế. Việc đáp ứng nhiều tính năng phần cứng là một khía cạnh quan trọng trong quá trình phát triển trò chơi. Tuy nhiên, trò chơi trên web có thể nhắm đến một phạm vi rộng hơn nhiều, bao gồm cả máy tính cao cấp và thiết bị di động đã qua một thập kỷ. Cách đơn giản nhất để tiếp cận vấn đề này là cung cấp các chế độ cài đặt nhằm điều chỉnh những nút thắt cổ chai có nhiều khả năng xảy ra nhất trong cơ sở mã của bạn – cho cả tác vụ cần nhiều GPU và CPU – theo tiết lộ của trình phân tích tài nguyên.

Tuy nhiên, việc phân tích tài nguyên trên máy của bạn chỉ có thể đáp ứng nhiều yêu cầu. Vì vậy, việc khép vòng lặp phản hồi với người dùng theo một cách nào đó là rất hữu ích. Đối với đường chậm, tôi chạy các số liệu phân tích đơn giản để báo cáo về hiệu suất cùng với các yếu tố theo ngữ cảnh như độ phân giải màn hình. Những số liệu phân tích này được gửi đến một phần phụ trợ Nút cơ bản bằng socket.io, cùng với mọi phản hồi bằng văn bản mà người dùng gửi thông qua biểu mẫu trong trò chơi. Trong những ngày đầu, các hoạt động phân tích này đã phát hiện thấy nhiều vấn đề quan trọng có thể giảm thiểu bằng các thay đổi đơn giản đối với trải nghiệm người dùng, chẳng hạn như làm nổi bật trình đơn cài đặt khi phát hiện FPS thấp một cách liên tục, hoặc cảnh báo rằng người dùng có thể cần bật tính năng tăng tốc phần cứng nếu hiệu suất đặc biệt kém.

Những con đường chậm phía trước

Ngay cả sau khi áp dụng tất cả các biện pháp này, vẫn còn một lượng đáng kể người chơi cần chơi ở chế độ cài đặt thấp hơn, chủ yếu là những người sử dụng thiết bị nhẹ không có GPU. Mặc dù các chế độ cài đặt chất lượng có sẵn giúp phân bổ hiệu suất khá đồng đều, nhưng chỉ 52% người chơi đạt được trên 55 khung hình/giây.

Một ma trận được xác định bằng chế độ cài đặt khoảng cách xem so với chế độ cài đặt chi tiết, cho thấy số khung hình/giây trung bình đạt được ở các cách ghép nối khác nhau. Mức phân bổ khá đồng đều từ 45 đến 60, trong đó 60 là mục tiêu để đạt hiệu suất tốt. Người dùng ở chế độ cài đặt thấp có xu hướng thấy FPS thấp hơn so với người dùng ở chế độ cài đặt cao, điều này làm nổi bật sự khác biệt về tính năng phần cứng của ứng dụng.
Xin lưu ý rằng dữ liệu này có phần sai lệch bởi những người dùng chạy trình duyệt đã tắt tính năng tăng tốc phần cứng. Điều này thường dẫn đến hiệu suất thấp một cách giả tạo.

May mắn là vẫn còn nhiều cơ hội để tiết kiệm hiệu suất. Ngoài việc bổ sung thêm các thủ thuật kết xuất để giảm nhu cầu kết xuất GPU, tôi hy vọng sẽ thử nghiệm song song việc tạo môi trường với worker trên web trong thời gian tới và cuối cùng có thể thấy nhu cầu kết hợp WASM hoặc WebGPU vào cơ sở mã. Bất kỳ mức trần nào mà tôi có thể giải phóng sẽ tạo điều kiện cho các môi trường phong phú và đa dạng hơn. Đây sẽ là mục tiêu lâu dài trong phần còn lại của dự án.

Khi các dự án theo sở thích của mình phát triển, Đường chậm trở thành một cách vô cùng thú vị để minh hoạ các trò chơi được công bố chi tiết, có hiệu suất cao và phổ biến đến mức đáng kinh ngạc. Nếu tôi đã thành công trong việc thu hút sự quan tâm của bạn về WebGL, hãy nhớ rằng công nghệ Đường có tốc độ chậm là một ví dụ tương đối nông về toàn bộ khả năng của WebGL. Tôi đặc biệt khuyến khích độc giả khám phá phần giới thiệu về Three.js. Đặc biệt, những độc giả quan tâm đến việc phát triển trò chơi trên web nên được chào mừng đến với cộng đồng tại webgamedev.com.