Tóm lại: Rải thủ tục chỉ đáng tin cậy nếu nó có thể tái tạo: cùng đầu vào phải luôn tạo ra cùng khu rừng, trên mỗi máy và mỗi bản build. Điều đó có nghĩa là hiểu seed (cách làm cho tính ngẫu nhiên có thể lặp lại), tại sao một hệ thống thủ tục sống động lại nguy hiểm dưới kiểm soát nguồn, và tại sao bake một rải vào các instance engine native biến một hộp đen không thể merge thành một tài sản có thể diff, review, có thể kiểm soát phiên bản. Bài viết này bao gồm tính quyết định, seed, và cách giữ cho tán lá của một nhóm không thay đổi âm thầm dưới chân mọi người.
Điều này trông ngẫu nhiên, nhưng đối với một nhóm, nó phải là tính ngẫu nhiên có thể lặp lại: giống trên máy bạn, máy đồng đội và máy chủ build. Tính quyết định là điều biến một rải đẹp thành một cái gì đó bạn thực sự có thể ship và duy trì.
Tại sao tính quyết định quan trọng
Nếu một rải tái tạo khác nhau mỗi lần nó được mở hoặc build, level của bạn thay đổi âm thầm: va chạm di chuyển, các đối tượng ẩn xuất hiện, playtest ngừng có thể tái tạo. Rải quyết định luôn tạo ra cùng kết quả chính xác từ cùng đầu vào.
Tính ngẫu nhiên không thể lặp lại là một nhà máy sản xuất lỗi trong một level. Nếu mở scene trên một máy khác, hoặc rebuild nó tuần tới, xáo trộn lại nơi mỗi tảng đá và bụi cây rơi xuống, thì một vị trí trước đây trống bây giờ bị chặn, một đường ngắm bạn đã tinh chỉnh bị phá vỡ, và một kết quả playtest không thể tin cậy được vì level đang thử nghiệm không phải là level bạn đã ship. Tính quyết định (cùng đầu vào, cùng đầu ra, luôn luôn) là điều làm cho một rải thủ tục an toàn. Đó là sự khác biệt giữa "máy tính đặt một số cây" và "level có một trạng thái xác định, ổn định mà tôi có thể dựa vào."
Seed: làm cho tính ngẫu nhiên có thể lặp lại
Seed là số bắt đầu cho một chuỗi ngẫu nhiên. Cùng seed → cùng vị trí "ngẫu nhiên" mỗi lần. Hiển thị và lưu seed, và rải của bạn có thể tái tạo; để nó cho tính ngẫu nhiên thực sự và nó là một level khác nhau trên mỗi lần chạy.
Máy tính không làm tính ngẫu nhiên thực sự: chúng chạy các chuỗi quyết định trông ngẫu nhiên, mỗi chuỗi được xác định bởi một số bắt đầu gọi là seed. Đưa cùng seed và bạn nhận được cùng chuỗi, do đó cùng vị trí, mỗi lần đơn lẻ. Đây là chìa khóa để rải có thể tái tạo: công cụ hiển thị một seed, bạn lưu nó với scene, và khu rừng bây giờ là một hàm thuần túy của (seed + tham số + bề mặt). Đổi seed để khám phá một sắp xếp khác mà bạn thích, sau đó khóa nó. Bất cứ điều gì thay vào đó rút từ một nguồn ngẫu nhiên thực sự không seed (đồng hồ, một lần tung mới mỗi lần mở) tạo ra một level khác nhau mỗi lần nó tải, mà không thể sử dụng cho sản xuất.
Vấn đề kiểm soát phiên bản
Một rải thủ tục sống động được lưu trữ dưới dạng "một hệ thống + tham số" là một hộp đen đối với kiểm soát nguồn: bạn không thể diff nó, review nó, và hai người chỉnh sửa nó tạo ra một xung đột không thể merge. Các nhóm cần rải ở dạng mà Git hoặc Perforce có thể thực sự theo dõi.
Đây là nơi rải gặp thực tế của một nhóm. Nếu khu rừng của bạn chỉ tồn tại như "một hệ thống rải với những cài đặt này", kiểm soát nguồn không thể thấy cái gì nó đã tạo ra; chỉ là một số tham số đã thay đổi. Bạn không thể review một thay đổi vị trí trong một pull request, bạn không thể nói cái gì đã di chuyển, và nếu hai nghệ sĩ chạm vào cùng một rải, bạn nhận được một xung đột merge mà không công cụ nào có thể giải quyết một cách có ý nghĩa. Một level đã rải chỉ sống bên trong một máy sinh sống động là vô hình đối với chính những hệ thống mà các nhóm dựa vào để cộng tác an toàn, đó là lý do tại sao "tất cả là thủ tục" có thể âm thầm trở thành "không ai có thể chỉnh sửa khu rừng an toàn."
Mỗi cái trong số này là một instance với một vị trí, xoay và tỷ lệ. Khi rải được bake vào các instance native, chúng trở thành dữ liệu thực, có thể kiểm tra: khu rừng ngừng là một công thức và trở thành một cái gì đó bạn có thể review từng dòng.
Bake làm cho nó có thể diff
Bake rải vào các instance engine native: các đối tượng được đặt thực với các biến đổi cụ thể. Bây giờ nó là dữ liệu scene thông thường: có thể diff, review, merge, và giống hệt trên mỗi máy vì nó được lưu trữ, không phải tái tạo.
Giải pháp cho cả tính quyết định và kiểm soát phiên bản là cùng động tác: bake. Thay vì ship một máy sinh sống động, bạn bake rải vào các instance engine native đơn giản: các mesh thực được đặt với các vị trí, xoay và tỷ lệ cụ thể được lưu trữ trong scene. Điều này sụp đổ mọi vấn đề cùng một lúc. Nó quyết định theo định nghĩa (nó là dữ liệu được lưu trữ, không phải một lần tung lại). Nó có thể diff (kiểm soát nguồn thấy các biến đổi cụ thể đã thay đổi). Nó có thể review (một lead có thể thấy chính xác cái gì đã di chuyển trong một pull request). Và nó không tốn cho engine bất cứ điều gì bất thường tại runtime, vì nó chỉ là các mesh được instance hóa. Một quy trình vẽ mật độ với các quy tắc và sau đó bake vào các instance native (chính xác cách Numivo hoạt động) cho bạn tốc độ authoring của rải thủ tục và độ ổn định của nội dung đặt tay, không có sự dễ vỡ hộp đen.
Giữ tán lá của một nhóm ổn định
Khóa seed, bake trước khi commit, và coi kết quả bake là nguồn sự thật. Rải lại một cách có chủ ý (tăng seed, review diff), không bao giờ vô tình, để khu rừng chỉ thay đổi khi ai đó muốn.
Kỷ luật thực tế cho một nhóm là ngắn. Khóa seed để rải có thể tái tạo. Bake trước khi commit, để những gì trong kiểm soát nguồn là kết quả cụ thể mà mọi người chia sẻ, không phải một công thức tung lại trên mỗi máy. Coi các instance đã bake là nguồn sự thật, thứ mà bạn review và ship. Và khi bạn muốn thay đổi khu rừng, làm điều đó có chủ ý: điều chỉnh tham số hoặc seed, bake lại, và review diff như bất kỳ thay đổi nào khác. Mục tiêu là một khu rừng chỉ thay đổi khi một con người quyết định nó nên, và mỗi thay đổi của nó là có thể thấy và có thể review, cùng tiêu chuẩn bạn sẽ giữ cho bất kỳ phần nào khác của level. Thủ tục vì tốc độ, đã bake vì ổn định: đó là toàn bộ thủ thuật.
Các con số thực địa đáng đánh cắp
- Quy tắc tính quyết định: cùng đầu vào → cùng đầu ra, luôn luôn, hoặc level của bạn trôi
- Một seed làm cho tính ngẫu nhiên có thể lặp lại: hiển thị nó, lưu nó, khóa nó
- Một rải thủ tục sống động là một hộp đen đối với Git/Perforce: không thể diff, không thể merge
- Bake vào các instance native → có thể diff, review, merge, giống hệt ở mọi nơi
- Thói quen nhóm: khóa seed → bake → commit; rải lại có chủ ý, không bao giờ vô tình
Hỏi-Đáp nhanh
Tôi không thể chỉ giữ rải thủ tục và không bao giờ bake sao? Cho một dự án đơn nhanh, có thể. Cho một nhóm hoặc bất cứ điều gì bạn sẽ duy trì, không: bạn mất diffing, review và merge an toàn, và bạn có nguy cơ trôi âm thầm. Bake là điều làm cho rải thủ tục an toàn sản xuất.
Chính xác tôi nên đặt gì dưới kiểm soát nguồn: cài đặt hay kết quả? Kết quả đã bake là nguồn sự thật; giữ cả cài đặt/seed để bạn có thể tái tạo có chủ ý. Chỉ commit cài đặt có nghĩa là kiểm soát nguồn không thể thấy điều gì đã thực sự thay đổi trong level.
Hai nghệ sĩ đã chỉnh sửa cùng khu rừng, chúng tôi merge thế nào? Với các instance đã bake, đó là dữ liệu scene thông thường và các công cụ merge bình thường của bạn áp dụng. Với một máy sinh sống động, thường không thể giải quyết; đó là lập luận cốt lõi cho bake trước khi commit và điều phối ai sở hữu một rải nhất định.
Bake có làm tôi mất khả năng tinh chỉnh sau này không? Không, giữ seed và tham số, và bake lại là một bước có chủ ý bất cứ khi nào bạn muốn thay đổi sắp xếp. Bạn nhận được lặp lại và ổn định, miễn là rải lại là một hành động có chủ ý, được review chứ không phải điều gì tự xảy ra.
Rải thủ tục kiếm được chỗ của nó chỉ khi nó có thể tái tạo. Khóa seed của bạn, bake vào các instance native, và coi kết quả bake đó là sự thật của level, và khu rừng của bạn trở thành một cái gì đó mà cả nhóm có thể xây dựng: nhanh để authoring, ổn định để ship, và an toàn để thay đổi chỉ khi ai đó muốn.

