Cây xanh là một trải nghiệm tham khảo nơi người chơi trồng và tưới hạt giống, để họ có thể sau này thu hoạch và bán những cây trồng thu được.

Dự án tập trung vào những trường hợp sử dụng phổ biến mà bạn có thể gặp phải khi phát triển một trải nghiệm trên Roblox. Ở những nơi thích hợp, bạn sẽ tìm thấy ghi chú về các sự đánh đổi, thỏa hiệp và lý do của các lựa chọn thực hiện khác nhau, để bạn có thể đưa ra quyết định tốt nhất cho những trải nghiệm của riêng bạn.
Nhận tệp
- Điều hướng đến trang trải nghiệm Cây xanh.
- Nhấp vào nút ⋯ và Chỉnh sửa trong Studio.
Các trường hợp sử dụng
Cây xanh bao gồm các trường hợp sử dụng sau:
- Dữ liệu phiên và khả năng duy trì dữ liệu người chơi
- Quản lý góc nhìn UI
- Kết nối máy chủ - khách
- Trải nghiệm người dùng lần đầu (FTUE)
- Mua bán tiền tệ cứng và mềm
Ngoài ra, dự án này giải quyết các tập hợp vấn đề hẹp hơn có thể áp dụng cho nhiều trải nghiệm, bao gồm:
- Tùy chỉnh một khu vực trong địa điểm gắn liền với một người chơi
- Quản lý tốc độ di chuyển của nhân vật người chơi
- Tạo một đối tượng theo sau các nhân vật
- Phát hiện xem nhân vật đang ở phần nào của thế giới
Lưu ý rằng có một số trường hợp sử dụng trong trải nghiệm này quá nhỏ, quá ngách, hoặc không thể hiện một giải pháp cho thách thức thiết kế thú vị; những điều này không được đề cập đến.
Cấu trúc dự án
Quyết định đầu tiên khi tạo một trải nghiệm là xác định cách cấu trúc dự án, bao gồm chủ yếu là nơi để đặt các thể hiện cụ thể trong mô hình dữ liệu và cách tổ chức và cấu trúc các điểm vào cho mã cả máy khách và máy chủ.
Mô hình dữ liệu
Bảng sau mô tả các dịch vụ chứa các thể hiện trong mô hình dữ liệu.
| Dịch vụ | Các loại thể hiện |
|---|---|
| Workspace | Chứa các mô hình tĩnh đại diện cho thế giới 3D, cụ thể là các phần của thế giới không thuộc về bất kỳ người chơi nào. Bạn không cần phải tạo, thay đổi hoặc phá hủy những thể hiện này tại thời gian chạy, vì vậy việc để chúng ở đây là chấp nhận được. Cũng có một Folder rỗng, trong đó mô hình trang trại của người chơi sẽ được thêm vào tại thời gian chạy. |
| Lighting | Các hiệu ứng khí quyển và ánh sáng. |
| ReplicatedFirst | Chứa tập con nhỏ nhất có thể của các thể hiện cần thiết để hiển thị màn hình tải và khởi tạo trải nghiệm. Càng có nhiều thể hiện được đặt vào ReplicatedFirst, thời gian chờ đợi để sao chép chúng trước khi mã trong ReplicatedFirst có thể chạy càng lâu.
|
| ReplicatedStorage | Đóng vai trò là một thùng chứa cho tất cả các thể hiện mà cần truy cập cả phía máy khách và máy chủ.
|
| ServerScriptService | Chứa một Script đóng vai trò là điểm vào cho tất cả mã phía máy chủ trong dự án. |
| ServerStorage | Đóng vai trò là một thùng chứa cho tất cả các thể hiện không cần sao chép đến máy khách.
|
| SoundService | Chứa các đối tượng Sound được sử dụng cho các hiệu ứng âm thanh trong trải nghiệm. Dưới SoundService, các đối tượng Sound này không có vị trí và không được mô phỏng trong không gian 3D. |
Điểm vào
Hầu hết các dự án tổ chức mã bên trong ModuleScripts có thể tái sử dụng có thể được nhập vào toàn bộ mã nguồn. ModuleScripts có thể tái sử dụng nhưng chúng không thực thi tự động; chúng cần được nhập bởi một Script hoặc LocalScript. Nhiều dự án Roblox sẽ có một số lượng lớn các đối tượng Script và LocalScript, mỗi đối tượng liên quan đến một hành vi hoặc hệ thống cụ thể trong trải nghiệm, tạo ra nhiều điểm vào.
Đối với trò chơi nhỏ Cây xanh, một cách tiếp cận khác được thực hiện thông qua một LocalScript duy nhất là điểm vào cho tất cả mã máy khách, và một Script duy nhất là điểm vào cho tất cả mã máy chủ. Cách tiếp cận đúng cho dự án của bạn phụ thuộc vào yêu cầu của bạn, nhưng một điểm vào duy nhất cung cấp kiểm soát lớn hơn về thứ tự trong đó các hệ thống được thực thi.
Danh sách sau mô tả những sự đánh đổi của cả hai phương pháp:
- Một Script duy nhất và một LocalScript duy nhất bao gồm mã máy chủ và máy khách tương ứng.
- Kiểm soát tốt hơn về thứ tự trong đó các hệ thống khác nhau được khởi động, vì tất cả mã được khởi tạo từ một kịch bản duy nhất.
- Có thể chuyển các đối tượng qua tham chiếu giữa các hệ thống.
Kiến trúc hệ thống cao cấp
Các hệ thống cấp cao trong dự án được chi tiết dưới đây. Một số hệ thống này phức tạp hơn nhiều so với những hệ thống khác, và trong nhiều trường hợp chức năng của chúng được trừu tượng hóa qua một hệ thống phân cấp các lớp khác.

Mỗi hệ thống này là một "singleton", nghĩa là nó là một lớp không thể hình thành mới mà thay vào đó được khởi tạo bởi kịch bản khởi động máy khách hoặc máy chủ liên quan. Bạn có thể đọc thêm về mô hình singleton sau trong hướng dẫn này.
Máy chủ
Các hệ thống sau liên quan đến máy chủ.
| Hệ thống | Mô tả |
|---|---|
| Mạng |
|
| PlayerDataServer |
|
| Thị trường |
|
| CollisionGroupManager |
|
| FarmManagerServer |
|
| Thùng chứa đối tượng người chơi |
|
| TagPlayers |
|
| FtueManagerServer |
|
| CharacterSpawner |
|
Máy khách
Các hệ thống sau liên quan đến máy khách.
| Hệ thống | Mô tả |
|---|---|
| Mạng |
|
| PlayerDataClient |
|
| MarketClient |
|
| LocalWalkJumpManager |
|
| FarmManagerClient |
|
| UISetup |
|
| FtueManagerClient |
|
| CharacterSprint |
|
Giao tiếp giữa máy khách và máy chủ
Hầu hết các trải nghiệm Roblox bao gồm một số yếu tố giao tiếp giữa máy khách và máy chủ. Điều này có thể bao gồm việc máy khách yêu cầu máy chủ thực hiện một hành động nhất định và máy chủ sao chép các bản cập nhật tới máy khách.
Trong dự án này, giao tiếp giữa máy khách và máy chủ được giữ càng tổng quát càng tốt bằng cách giới hạn việc sử dụng các đối tượng RemoteEvent và RemoteFunction nhằm giảm bớt số lượng quy tắc đặc biệt cần theo dõi. Dự án này sử dụng các phương thức sau, theo thứ tự ưu tiên:
- Sao chép thông qua hệ thống dữ liệu người chơi.
- Sao chép thông qua thuộc tính.
- Sao chép thông qua thẻ.
- Gửi tin nhắn trực tiếp thông qua mô-đun Mạng.
Sao chép thông qua hệ thống dữ liệu người chơi
Hệ thống dữ liệu người chơi cho phép dữ liệu được liên kết với người chơi mà vẫn tồn tại giữa các phiên lưu trữ. Hệ thống này cung cấp sao chép từ máy khách đến máy chủ và một tập hợp các API có thể được sử dụng để truy vấn dữ liệu và đăng ký các thay đổi, làm cho nó lý tưởng cho việc sao chép các thay đổi trạng thái người chơi từ máy chủ đến máy khách.
Ví dụ, thay vì gửi một UpdateCoins RemoteEvent đặt riêng để nói cho máy khách biết họ có bao nhiêu đồng xu, bạn có thể gọi câu lệnh sau và để cho máy khách đăng ký thông qua sự kiện PlayerDataClient.updated .
PlayerDataServer.setValue(player, "coins", 5)
Tất nhiên, điều này chỉ có ích cho việc sao chép từ máy chủ đến máy khách và cho các giá trị mà bạn muốn tồn tại giữa các phiên, nhưng điều này áp dụng cho một số trường hợp đáng ngạc nhiên trong dự án, bao gồm:
- Giai đoạn FTUE hiện tại
- Kho đồ của người chơi
- Số lượng xu mà người chơi đang có
- Trạng thái trang trại của người chơi
Sao chép thông qua thuộc tính
Trong các tình huống mà máy chủ cần sao chép một giá trị tùy chỉnh đến máy khách cụ thể cho một Instance nhất định, bạn có thể sử dụng các thuộc tính. Roblox tự động sao chép các giá trị thuộc tính, vì vậy bạn không cần duy trì bất kỳ con đường mã nào để sao chép trạng thái liên quan đến một đối tượng. Một lợi ích khác là quá trình sao chép này được thực hiện cùng với chính thể hiện đó.
Điều này đặc biệt hữu ích cho các thể hiện được tạo ra ở thời gian chạy, vì các thuộc tính được đặt trên một thể hiện mới trước khi nó được gán là cha của mô hình dữ liệu sẽ sao chép một cách nguyên tử cùng với chính thể hiện đó. Điều này giúp tránh cần viết mã để "chờ" dữ liệu bổ sung được sao chép qua một RemoteEvent hoặc StringValue.
Bạn cũng có thể đọc trực tiếp thuộc tính từ mô hình dữ liệu, từ cả máy khách hoặc máy chủ, bằng phương thức GetAttribute() và đăng ký các thay đổi bằng cách sử dụng GetAttributeChangedSignal(). Trong dự án Cây xanh, tiếp cận này được sử dụng cho, bên cạnh những thứ khác, để sao chép trạng thái hiện tại của cây đến máy khách.
Sao chép thông qua thẻ
CollectionService cho phép bạn áp dụng một thẻ chuỗi cho một Instance. Điều này hữu dụng cho việc phân loại các thể hiện và sao chép phân loại đó đến máy khách.
Ví dụ, thẻ CanPlant được áp dụng trên máy chủ để báo hiệu cho máy khách rằng một chậu nhất định có thể nhận được một cây.
Gửi tin nhắn trực tiếp thông qua mô-đun mạng
Đối với những tình huống mà không có tùy chọn nào trước đó áp dụng, bạn có thể sử dụng các cuộc gọi mạng tùy chỉnh thông qua mô-đun Mạng. Đây là tùy chọn duy nhất trong dự án cho phép giao tiếp từ máy khách đến máy chủ và do đó cho phép việc truyền tải các yêu cầu từ máy khách và nhận phản hồi từ máy chủ.
Cây xanh sử dụng gọi mạng trực tiếp cho một loạt các yêu cầu từ máy khách, bao gồm:
- Tưới một cây
- Trồng một hạt giống
- Mua một mặt hàng
Nhược điểm của cách tiếp cận này là mỗi tin nhắn riêng lẻ yêu cầu một số cấu hình đặt riêng có thể làm tăng độ phức tạp của dự án, mặc dù điều này đã được tránh càng nhiều càng tốt, đặc biệt là đối với giao tiếp từ máy chủ đến máy khách.
Các lớp và singleton
Các lớp trong dự án Cây xanh, giống như các thể hiện trên Roblox, có thể được tạo và bị hủy. Cú pháp lớp của nó được lấy cảm hứng từ cách tiếp cận Lua đối với lập trình hướng đối tượng với một số thay đổi để hỗ trợ cho kiểm tra kiểu chặt chẽ.
Khởi tạo
Nhiều lớp trong dự án gắn liền với một hoặc nhiều Instances. Các đối tượng của một lớp nhất định được tạo ra bằng cách sử dụng phương thức new(), nhất quán với cách các thể hiện được tạo trong Roblox sử dụng Instance.new().
Mô hình này thường được sử dụng cho các đối tượng mà lớp có một đại diện vật lý trong mô hình dữ liệu, và lớp mở rộng chức năng của nó. Một ví dụ điển hình là BeamBetween tạo ra một đối tượng Beam giữa hai đối tượng Attachment nhất định và giữ cho những gắn kết đó định hướng để tia luôn hướng lên. Những thể hiện này có thể được sao chép từ một phiên bản được sản xuất sẵn trong ReplicatedStorage hoặc được truyền vào new() như một đối số và được lưu trữ bên trong đối tượng dưới self.
Các thể hiện tương ứng
Như đã đề cập ở trên, nhiều lớp trong dự án này có một đại diện mô hình dữ liệu, một thể hiện tương ứng với lớp và được thao tác bởi lớp đó.
Thay vì tạo những thể hiện này khi một đối tượng lớp được khởi tạo, mã thường chọn để Clone() một phiên bản được sản xuất sẵn của Instance được lưu trữ dưới ReplicatedStorage hoặc ServerStorage. Mặc dù có thể tuần tự hóa các thuộc tính của những thể hiện này và tạo chúng từ đầu trong các hàm new() của lớp, điều này sẽ khiến cho việc chỉnh sửa các đối tượng trở nên khá khó khăn và khiến cho việc đọc hiểu trở nên khó khăn hơn. Ngoài ra, việc sao chép một thể hiện thường là một thao tác nhanh hơn so với việc tạo một thể hiện mới và tùy chỉnh các thuộc tính của nó tại thời gian chạy.
Thành phần
Mặc dù thừa kế là có thể trong Luau bằng cách sử dụng các bảng, dự án chọn cho phép các lớp mở rộng lẫn nhau thông qua thành phần. Khi kết hợp các lớp thông qua thành phần, đối tượng "con" được khởi tạo trong phương thức new() của lớp và được bao gồm như một thành viên dưới self.
Để xem ví dụ về điều này, hãy xem lớp CloseButton bọc lớp Button.
Dọn dẹp
Tương tự như cách một Instance có thể bị phá hủy bằng phương thức Destroy(), các lớp có thể được khởi tạo cũng có thể bị phá hủy. Phương thức hủy cho các lớp dự án là destroy() được viết thường với chữ d cho tính nhất quán của kiểu camelCase trong các phương thức của mã nguồn, cũng như để phân biệt giữa các lớp của dự án và các thể hiện Roblox.
Vai trò của phương thức destroy() là để phá hủy bất kỳ thể hiện nào được tạo bởi đối tượng, ngắt kết nối bất kỳ kết nối nào, và gọi destroy() trên bất kỳ đối tượng con nào. Điều này đặc biệt quan trọng đối với các kết nối vì các thể hiện có kết nối hoạt động không được dọn dẹp bởi bộ thu gom rác Luau, ngay cả khi không còn bất kỳ tham chiếu nào đến thể hiện hoặc các kết nối với thể hiện đó.
Singleton
Singleton, như tên gọi cho thấy, là các lớp mà chỉ một đối tượng có thể tồn tại. Chúng tương đương với Các dịch vụ của Roblox. Thay vì lưu trữ một tham chiếu đến đối tượng singleton và chuyển nó xung quanh trong mã Luau, Cây xanh tận dụng thực tế rằng việc yêu cầu một ModuleScript sẽ lưu trữ giá trị trả về của nó. Điều này có nghĩa là việc yêu cầu cùng một ModuleScript singleton từ các nơi khác nhau liên tục cung cấp cùng một đối tượng trả về. Ngoại lệ duy nhất cho quy tắc này sẽ là nếu các môi trường khác nhau (máy khách hoặc máy chủ) truy cập cùng một ModuleScript.
Singleton được phân biệt với các lớp có thể hình thành mới bằng thực tế rằng chúng không có phương thức new(). Thay vào đó, đối tượng cùng với các phương thức và trạng thái của nó được trả về trực tiếp thông qua ModuleScript. Vì singleton không được khởi tạo, cú pháp self không được sử dụng và các phương thức được gọi bằng dấu chấm (.) thay vì dấu hai chấm (:).
Kiểm tra kiểu chặt chẽ
Luau hỗ trợ kiểu dần dần có nghĩa là bạn có thể thêm định nghĩa kiểu tùy chọn cho một số hoặc tất cả mã của bạn. Trong dự án này, kiểm tra kiểu strict đã được sử dụng cho mọi kịch bản. Đây là tùy chọn ít cho phép nhất đối với công cụ Phân tích Kịch bản của Roblox và do đó có khả năng phát hiện lỗi kiểu trước khi chạy.
Cú pháp lớp có kiểu
Cách tiếp cận đã được xác định để tạo các lớp trong Lua đã được ghi chép đầy đủ, tuy nhiên nó không phù hợp với kiểu mạnh của Luau. Trong Luau, cách tiếp cận đơn giản nhất để lấy kiểu của một lớp là phương thức typeof():
type ClassType = typeof(Class.new())
Cách này hiệu quả nhưng không hữu ích khi lớp của bạn được khởi tạo với các giá trị chỉ tồn tại tại thời gian chạy, ví dụ như các đối tượng Player. Ngoài ra, giả định được đưa ra trong cú pháp lớp Lua là khi định nghĩa một phương thức trên self là nó sẽ luôn là một thể hiện của lớp đó; đây không phải là giả định mà bộ suy diễn kiểu có thể đưa ra.
Để hỗ trợ cho việc suy diễn kiểu chặt chẽ, dự án Cây xanh sử dụng giải pháp khác với cú pháp lớp Lua thông thường theo nhiều cách, một số cách này có thể cảm thấy không trực quan:
- Định nghĩa của self được sao chép, cả trong khai báo kiểu và trong trình khởi tạo. Điều này tạo ra gánh nặng bảo trì, nhưng sẽ có cảnh báo nếu hai định nghĩa không đồng bộ với nhau.
- Phương thức lớp được khai báo bằng dấu chấm, vì vậy self có thể được khai báo rõ ràng là kiểu ClassType. Các phương thức vẫn có thể được gọi với dấu hai chấm như mong đợi.
--!strict
local MyClass = {}
MyClass.__index = MyClass
export type ClassType = typeof(setmetatable(
{} :: {
property: number,
},
MyClass
))
function MyClass.new(property: number): ClassType
local self = {
property = property,
}
setmetatable(self, MyClass)
return self
end
function MyClass.addOne(self: ClassType)
self.property += 1
end
return MyClass
Ép kiểu sau các bộ bảo vệ logic
Tại thời điểm viết, kiểu của một giá trị không được thu hẹp sau một câu lệnh điều kiện bảo vệ. Ví dụ, sau bộ bảo vệ dưới đây, kiểu của optionalParameter không được thu hẹp thành number.
--!strict
local function foo(optionalParameter: number?)
if not optionalParameter then
return
end
print(optionalParameter + 1)
end
Để giảm thiểu điều này, các biến mới được tạo ra sau các bộ bảo vệ này với kiểu rõ ràng được ép.
--!strict
local function foo(optionalParameter: number?)
if not optionalParameter then
return
end
local parameter = optionalParameter :: number
print(parameter + 1)
end
Duyệt qua các cấu trúc DataModel
Trong một số trường hợp, mã nguồn cần phải duyệt qua cấu trúc mô hình dữ liệu của một cây các đối tượng được tạo ra tại thời gian chạy. Điều này xuất hiện một thách thức thú vị cho việc kiểm tra kiểu. Tại thời điểm viết, không thể định nghĩa một cấu trúc cây mô hình dữ liệu như một kiểu. Do đó, có những trường hợp mà thông tin kiểu duy nhất có sẵn cho một cấu trúc mô hình dữ liệu là kiểu của thể hiện cấp cao nhất.
Một cách tiếp cận cho thách thức này là ép kiểu thành any và sau đó tinh chỉnh. Ví dụ:
local function enableVendor(vendor: Model)
local zonePart: BasePart = (vendor :: any).ZonePart
end
Vấn đề với cách tiếp cận này là nó ảnh hưởng đến khả năng đọc. Thay vào đó, dự án sử dụng một mô-đun tổng quát có tên getInstance để duyệt qua các cấu trúc cây mô hình dữ liệu mà ép thành any bên trong.
local function enableVendor(vendor: Model)
local zonePart: BasePart = getInstance(vendor, "ZonePart")
end
Khi sự hiểu biết của bộ kiểm tra kiểu về mô hình dữ liệu phát triển, có thể rằng các mẫu như thế này sẽ không còn cần thiết nữa.
Giao diện người dùng
Cây xanh bao gồm nhiều giao diện người dùng 2D phức tạp và đơn giản. Những giao diện này bao gồm các mục hiển thị không tương tác như bộ đếm xu và các menu tương tác phức tạp như cửa hàng.
Cách tiếp cận UI
Bạn có thể so sánh một cách lỏng lẻo giao diện UI trên Roblox với DOM HTML, bởi vì nó là một cấu trúc phân cấp các đối tượng mô tả những gì người dùng nên thấy. Các cách tiếp cận để tạo và cập nhật giao diện Roblox được chia thành hai thực tiễn chính là mệnh lệnh và khai báo.
| Cách tiếp cận | Lợi thế và nhược điểm |
|---|---|
| Mệnh lệnh | Trong cách tiếp cận mệnh lệnh, giao diện người dùng được coi như bất kỳ cấu trúc thể hiện nào khác trên Roblox. Cấu trúc giao diện được tạo ra trước thời gian chạy trong Studio và thêm vào mô hình dữ liệu, thường được thêm trực tiếp vào StarterGui. Sau đó, tại thời gian chạy, mã thao tác các phần cụ thể của giao diện để phản ánh trạng thái mà người tạo yêu cầu. Cách tiếp cận này có một số lợi ích. Bạn có thể tạo giao diện từ đầu trong Studio và lưu trữ nó trong mô hình dữ liệu. Đây là một trải nghiệm chỉnh sửa đơn giản và trực quan có thể tăng tốc việc tạo giao diện. Bởi vì mã giao diện mệnh lệnh chỉ quan tâm đến những gì cần thay đổi, nó cũng làm cho các thay đổi giao diện đơn giản trở nên dễ dàng để thực hiện. Một nhược điểm đáng chú ý là, khi các cách tiếp cận giao diện mệnh lệnh yêu cầu trạng thái phải được thực hiện thủ công dưới dạng các biến đổi, các đại diện phức tạp của trạng thái có thể trở nên rất khó khăn để tìm và gỡ lỗi. Thường thì sẽ xuất hiện các lỗi khi phát triển mã giao diện mệnh lệnh, đặc biệt khi trạng thái và giao diện không còn đồng bộ với nhau do nhiều cập nhật tương tác theo thứ tự không như mong đợi. Một thách thức khác đối với các cách tiếp cận mệnh lệnh là việc khó khăn hơn trong việc phân chia giao diện thành các thành phần có ý nghĩa mà có thể được khai báo một lần và tái sử dụng. Bởi vì toàn bộ cây giao diện được khai báo tại thời điểm chỉnh sửa, các mẫu phổ biến có thể bị lặp lại ở nhiều phần khác nhau của mô hình dữ liệu. |
| Khai báo | Trong cách tiếp cận khai báo, trạng thái mong muốn của các thể hiện giao diện được khai báo rõ ràng, và việc thực hiện hiệu quả của trạng thái này được trừu tượng hóa bởi các thư viện như Roact hoặc Fusion. Lợi ích của cách tiếp cận này là việc thực hiện trạng thái trở nên đơn giản và bạn chỉ cần mô tả những gì bạn muốn giao diện của bạn trông như thế nào. Điều này làm cho việc xác định và giải quyết lỗi dễ dàng hơn rất nhiều. Nhược điểm chính là phải khai báo toàn bộ cây giao diện trong mã. Các thư viện như Roact và Fusion có cú pháp để làm cho điều này dễ hơn, nhưng đó vẫn là một quá trình tốn thời gian và là một trải nghiệm chỉnh sửa kém trực quan khi kết hợp giao diện. |
Cây xanh sử dụng một cách tiếp cận mệnh lệnh dưới quan điểm rằng việc hiển thị các biến đổi trực tiếp cung cấp một cái nhìn tổng thể hiệu quả hơn về cách giao diện được tạo ra và thao tác trên Roblox. Điều này sẽ không thể có được với cách tiếp cận khai báo. Một số cấu trúc giao diện người dùng và logic lặp lại cũng được trừu tượng hóa thành các thành phần có thể tái sử dụng nhằm tránh một bẫy phổ biến trong thiết kế giao diện UI mệnh lệnh.
Kiến trúc cấp cao

Lớp và thành phần
Trong Cây xanh, tất cả các cấu trúc UI đều là một Layer hoặc một Component.
- Layer được định nghĩa là một lớp nhóm cấp cao bao gồm các cấu trúc UI được sản xuất sẵn trong ReplicatedStorage. Một lớp có thể chứa một số thành phần, hoặc nó có thể bao gồm logic của chính nó. Ví dụ về lớp là menu kho đồ hoặc số lượng xu trong hiển thị lên đầu.
- Component là một phần tử UI có thể tái sử dụng. Khi một đối tượng thành phần mới được khởi tạo, nó sao chép một mẫu được sản xuất sẵn từ ReplicatedStorage. Các thành phần có thể chứa các thành phần khác. Ví dụ về các thành phần là một lớp nút tổng quát hoặc khái niệm về danh sách các mặt hàng.
Quản lý góc nhìn
Một vấn đề quản lý giao diện phổ biến là quản lý góc nhìn. Dự án này có một loạt các menu và các mục HUD, một số trong số đó lắng nghe đầu vào của người dùng, và việc quản lý cẩn thận khi nào chúng hiển thị hoặc được bật là cần thiết.
Cây xanh tiếp cận vấn đề này với hệ thống UIHandler của nó, quản lý khi nào một lớp UI nên hoặc không nên hiển thị. Tất cả các lớp UI trong trải nghiệm được phân loại là HUD hoặc Menu và trạng thái hiển thị của chúng được quản lý theo các quy tắc sau:
- Trạng thái được bật của các lớp Menu và HUD có thể được chuyển đổi.
- Các lớp HUD được bật chỉ được hiển thị nếu không có Menu nào đang được bật.
- Các lớp Menu được bật được lưu trữ trong một ngăn xếp, và chỉ một lớp Menu được hiển thị tại một thời điểm. Khi một lớp Menu được bật, nó sẽ được chèn vào đầu ngăn xếp và được hiển thị. Khi một lớp Menu bị tắt, nó sẽ được xóa khỏi ngăn xếp và lớp Menu được tiếp theo trong hàng đợi sẽ được hiển thị.
Cách tiếp cận này rất trực quan vì nó cho phép điều hướng các menu với lịch sử. Nếu một menu được mở từ một menu khác, việc đóng menu mới sẽ lại hiển thị menu cũ.
Các singleton lớp UI tự đăng ký với UIHandler và được cung cấp một tín hiệu sẽ phát khi trạng thái hiển thị của nó nên thay đổi.
Đọc thêm
Từ cái nhìn tổng quan đầy đủ về dự án Cây xanh, bạn có thể muốn khám phá các hướng dẫn sau đây đi sâu hơn vào các khái niệm và chủ đề liên quan.
- Mô hình Máy khách-Máy chủ — Một cái nhìn tổng quan về mô hình máy khách-máy chủ trong Roblox.
- Sự kiện từ xa và Callbacks — Tất cả về các sự kiện mạng từ xa và callbacks để giao tiếp qua ranh giới máy khách-máy chủ.
- Giao diện Người dùng (UI) — Thông tin chi tiết về các đối tượng giao diện người dùng và thiết kế trên Roblox.