Thiết Kế Hệ Thống Tệp Tài Nguyên
Trong lần trước, chúng ta đã đề cập đến việc engine sẽ được phát triển trên nền tảng PC và trực tiếp gỡ lỗi trên thiết bị. Theo phương pháp phát triển truyền thống - đóng gói ứng dụng rồi mới chạy - chắc chắn không thể đáp ứng được nhu cầu phát triển nhanh. Do đó, một cơ chế đồng bộ tài nguyên hiệu quả là điều kiện tiên quyết.
Hiện tại, chúng tôi đã hoàn thành phiên bản cốt lõi của hệ thống tệp tài nguyên với cơ chế hoạt động như sau: Toàn bộ các tệp tài nguyên bao gồm cả mã nguồn (viết bằng Lua) đều được lưu trữ trên máy tính phát triển. Môi trường phát triển sẽ lưu trữ giá trị md5 của từng tệp. Hệ thống tệp sử dụng giá trị md5 này làm chuẩn xác định tính đồng nhất của tệp. Ở giai đoạn này, chúng tôi tạm thời bỏ qua khả năng xảy ra va chạm md5.
Trên thiết bị, chúng tôi triển khai cơ chế lưu trữ tạm thời (cache) bằng hệ thống tệp địa phương, chia làm hai khu vực chính:
- Khu vực tài nguyên: Các tệp được lưu với tên tệp là giá trị md5 của chúng (sử dụng 3 byte đầu tiên của chuỗi md5 dạng hex để phân bổ vào các thư mục con, tránh tình trạng quá nhiều tệp trong một thư mục)
- Khu vực cấu trúc thư mục: Mỗi thư mục con được đánh số ID tăng dần, chứa thông tin tên gốc có thể đọc được cùng với giá trị md5 tương ứng hoặc ID các thư mục con. Trong đó, ID 0 đại diện cho thư mục gốc của tài nguyên.
Ví dụ minh họa:
- Có tệp kết cấu
foobar.tex
tại đường dẫntextures/foobar.tex
với giá trị md5 làxxxxxx
. - Trong tệp ID 0 (thư mục gốc), sẽ có dòng ghi nhận:
textures 1
-> cho biết thư mụctextures
tồn tại với ID 1. - Tiếp tục mở tệp ID 1, tìm thấy bản ghi:
foobar.tex xxxxxx
-> xác nhận sự tồn tại của tệpfoobar.tex
có giá trị md5xxxxxx
. - Khi cần truy xuất
textures/foobar.tex
, hệ thống sẽ:- Đọc tệp gốc (ID 0) để tìm ID thư mục
textures
là 1 - Mở tệp ID 1 xác định tệp
foobar.tex
có md5xxxxxx
- Sử dụng giá trị md5 để truy xuất tệp từ khu vực tài nguyên
- Đọc tệp gốc (ID 0) để tìm ID thư mục
Trong quá trình chạy game:
- Mô-đun IO chịu trách nhiệm quản lý tài nguyên:
- Nếu chưa có tệp trong cache: Gửi yêu cầu lấy tệp từ máy chủ phát triển
- Nếu tệp đã tồn tại: Gửi yêu cầu xác minh md5, chỉ tải lại khi phát hiện sự khác biệt
Đề xuất tối ưu tương lai: Thêm trường phiên bản (version number) vào các tệp thư mục. Phiên bản sẽ được đồng bộ khi khởi động và sử dụng để giảm thiểu số lượng yêu cầu xác minh tệp.
Lưu ý đặc biệt về quản lý cache:
- Mô-đun IO không xóa vật lý các tệp dù người dùng có thực hiện thao tác xóa. Thay vào đó chỉ xóa bản ghi tham chiếu trong tệp thư mục. Điều này đặc biệt hữu ích khi:
- Cần chuyển đổi nhanh giữa nhiều phiên bản phát triển
- Di chuyển thiết bị giữa các máy tính ở nhánh phát triển khác nhau
- Cache có thể được dọn dẹp chủ động bằng hai cách:
- Xóa toàn bộ cache
- Duyệt ngược từ gốc xuống tìm các tệp không còn tham chiếu để xóa
Lợi ích bất ngờ từ cơ chế md5: Việc sử dụng md5 làm khóa định danh cho phép người dùng tổ chức tài nguyên linh hoạt hơn. Ví dụ: Hai mô hình cần dùng chung kết cấu, thay vì phải đặt tệp kết cấu ở thư mục chung riêng biệt, bạn có thể đặt trực tiếp trong thư mục mô hình tương ứng. Hệ thống tự động đảm bảo chỉ lưu một bản duy nhất trong thiết bị, đồng thời ngăn chặn việc tải trùng lặp vào bộ nhớ.
Chi tiết kỹ thuật bổ sung:
-
Xử lý yêu cầu bất đồng bộ bằng Lua:
- Khi phần giao tiếp mạng được viết bằng Lua, cần tận dụng coroutine để tải tài nguyên không chặn luồng chính
- Lưu ý: Hàm
require
gốc của Lua được viết bằng C, không thể sử dụngcoroutine.yield
trực tiếp trong loader - Giải pháp: Xây dựng hàm
require
tùy biến, kiểm trapackage.loaded
vàpackage.searchpath
trong Lua trước, sau đó chuyển sang hàmrequire
chuẩn khi hoàn tất tải bất đồng bộ
-
Tối ưu bằng lệnh prefetch: Mô-đun IO cung cấp lệnh
prefetch
cho phép gửi trước các yêu cầu tệp mà không làm gián đoạn luồng xử lý chính. Tính năng này có thể được sử dụng ở tầng quản lý tài nguyên cao hơn:- Khi phân tích được mối quan hệ phụ thuộc giữa các tài nguyên, có thể gửi đồng loạt tất cả yêu cầu phụ thuộc sau khi tải mỗi tệp
- Đặc biệt với tệp Lua: Có thể phân tích trước khi thực thi để phát hiện các yêu cầu
require
mới và gửi đồng loạt các tệp liên quan