Tạo giao diện người dùng tương tác

*Nội dung này được dịch bằng AI (Beta) và có thể có lỗi. Để xem trang này bằng tiếng Anh, hãy nhấp vào đây.

Một HUD (Heads-Up Display) trong trò chơi của bạn thường hiển thị các yếu tố UI không tương tác như đồng hồ sức khỏe được trình bày trong Tạo đồng hồ HUD. Ngoài ra, hầu hết mọi trò chơi đều yêu cầu UI tương tác như các nút phản hồi khi người chơi kích hoạt, hoạt hình khi được kích hoạt, tween vào/ra các menu với các điều khiển tương tác khác, v.v.

Giao diện trong trò chơi hiển thị nút cài đặt và menu cài đặt với các thanh trượt âm lượng.

Sử dụng Cơ bản về UI - Đồng hồ HUD làm điểm khởi đầu và Cơ bản về UI - Tương tác làm tài liệu tham khảo hoàn chỉnh, hướng dẫn này trình bày:

  • Cách định vị một nút cài đặt dọc theo cạnh trên của màn hình.
  • Thiết kế một menu cài đặt chứa các thanh trượt kéo tương tác.
  • Sử dụng một ModuleScripts để tạo ra các module "controller" cho việc điều khiển mở rộng các đối tượng UI với các khai báo có trạng thái.
  • Cách kết nối các nút với việc kích hoạt của người chơi để bật/tắt menu cài đặt.
  • Cách kết nối các thanh trượt UI kéo để điều chỉnh âm lượng của hiệu ứng âm thanh và âm thanh nền một cách riêng biệt.

Kích hoạt Trình giả lập Thiết bị

Như đã đề cập trong Tạo đồng hồ HUD, điện thoại và máy tính bảng có ít không gian màn hình nhất, vì vậy điều quan trọng là các yếu tố UI của bạn phải vừa vặn trên các màn hình nhỏ hơn và rõ ràng với người chơi. Nếu bạn chưa làm như vậy, hãy kích hoạt Trình giả lập Thiết bị trong Studio:

  1. Mở mẫu Cơ bản về UI - Đồng hồ HUD trong Studio.

  2. Từ menu Test của Studio, bật Trình giả lập Thiết bị.

  3. Từ thanh ngay trên viewport chính, chọn một mô phỏng điện thoại như iPhone X hoặc Samsung Galaxy A51. Sau đó, đặt kích thước xem thành Vừa với Cửa sổ để sử dụng tối đa không gian trong Studio.

    Các tùy chọn cài đặt Trình giả lập Thiết bị được chỉ định ở đầu cửa sổ viewport.

Tạo nút cài đặt

GuiButtons là các yếu tố giao diện người dùng tương tác với chức năng tích hợp sẵn như sự kiện đa nền tảng Activated được kích hoạt khi nút được nhấp hoặc chạm. Lớp GuiButton mở rộng đến hai biến thể, TextButtonImageButton, và hướng dẫn này sử dụng một ImageButton hình "bánh răng" để bật hoặc tắt menu cài đặt.

Thành phần Roblox được sử dụng cho nút cài đặt.

Để xây dựng nút cài đặt:

  1. Trong cửa sổ Explorer, tìm HUDContainer bên trong StarterGui.

    Cửa sổ Explorer hiển thị HUDContainer được chọn.
  2. Chèn một ImageButton vào HUDContainer và đổi tên thành SettingsButton.

    Cửa sổ Explorer hiển thị nút ImageButton mới được chèn và đổi tên thành SettingsButton. Nút ImageButton mới trong viewport.
  3. Với nút mới được chọn, đặt các thuộc tính sau trong cửa sổ Properties:

    • AnchorPoint = 0.5, 0.25 (giữa theo chiều ngang và phần tư trên theo chiều dọc)
    • BackgroundTransparency = 1 (hoàn toàn trong suốt)
    • Position = 0.5, 0, 0, 0 (định vị ở giữa trên)
    • Size = 0.1, 0, 0.1, 0 (10% chiều cao màn hình khi tỷ lệ khung hình được ràng buộc)
    • Image = rbxassetid://104919049969988 (ID tài sản của biểu tượng "bánh răng")
  4. Chèn một UIAspectRatioConstraint vào nút với các thuộc tính mặc định (tỷ lệ 1:1 giữa chiều rộng và chiều cao).

    Cửa sổ Explorer hiển thị một UIAspectRatioConstraint mới được chèn vào nút SettingsButton.
  5. Để giới hạn chiều cao pixel tối đa của nút, chèn một UISizeConstraint và đặt MaxSize thành inf, 44.

    Cửa sổ Explorer hiển thị một UISizeConstraint mới được chèn vào nút SettingsButton.
    Cửa sổ Properties hiển thị các giá trị mong đợi cho UISizeConstraint mới.
    Nút cài đặt cuối cùng ở giữa trên màn hình.

Tạo menu cài đặt

Nút cài đặt mới sẽ được lập trình để bật và tắt menu cài đặt, cung cấp cho người chơi quyền truy cập theo yêu cầu vào các cài đặt hoặc thông tin khác. Trong hướng dẫn này, menu sẽ chứa các thanh trượt tương tác để điều chỉnh mức âm lượng của âm thanh nền và hiệu ứng âm thanh một cách độc lập.

Các thành phần cơ bản được sử dụng cho menu cài đặt.

Tạo khung cha

Như đã đề cập trong Tạo đồng hồ HUD, một Frame phục vụ như một container cho các đối tượng UI khác. Toàn bộ menu cài đặt sẽ được xây dựng với một khung cha duy nhất, giúp dễ dàng quản lý như một đối tượng có trạng thái phản ứng với đầu vào khác nhau tùy thuộc vào trạng thái hiện tại.

  1. Chèn một Frame vào HUDContainer và đổi tên thành SettingsMenu.

    Cửa sổ Explorer hiển thị khung mới được chèn và đổi tên thành SettingsMenu.
  2. Với SettingsMenu được chọn, đặt các thuộc tính sau:

    Khung được định vị lại, thay đổi kích thước và được tạo kiểu với nền xanh hải quân trong suốt.
  3. Chèn một UIAspectRatioConstraint vào SettingsMenu và đặt thuộc tính AspectRatio của nó thành 2.5. (tỷ lệ 2.5:1 giữa chiều rộng và chiều cao).

    Cửa sổ Explorer hiển thị một UISizeConstraint mới được chèn vào khung SettingsMenu.
    Cửa sổ Properties hiển thị các giá trị mong đợi cho UISizeConstraint mới.
  4. Chèn một bộ điều chỉnh UICorner vào SettingsMenu và đặt thuộc tính CornerRadius của nó thành 0.1, 0.

    Cửa sổ Explorer hiển thị một UICorner mới được chèn vào khung SettingsMenu.
    Cửa sổ Properties hiển thị các giá trị mong đợi cho bộ điều chỉnh UICorner mới.
  5. Để ràng buộc chiều rộng và chiều cao pixel của SettingsMenu, chèn một UISizeConstraint. Đặt MaxSize của nó thành 800, infMinSize của nó thành 350, 0.

    Cửa sổ Explorer hiển thị một UISizeConstraint mới được chèn vào khung SettingsMenu.
    Cửa sổ Properties hiển thị các giá trị mong đợi cho UISizeConstraint mới.
    Khung được tạo kiểu với các góc tròn.

Xây dựng một thanh trượt

Để cho phép người chơi điều chỉnh mức âm lượng, menu cài đặt sẽ chứa hai widget thanh trượt có thể kéo được điều khiển bởi UIDragDetector, một đối tượng tiện lợi giúp tương tác với các yếu tố giao diện người dùng 2D.


Để tạo một container cha cho thanh trượt đầu tiên:

  1. Chèn một Frame mới vào container SettingsMenu và đổi tên thành EffectsVolumeSlider.

    Cửa sổ Explorer hiển thị một khung mới được chèn vào khung SettingsMenu, đổi tên thành EffectsVolumeSlider.
  2. Với khung EffectsVolumeSlider được chọn, đặt các thuộc tính sau:

    • AnchorPoint = 0.5 (neo ở giữa)

    • BackgroundTransparency = 1 (hoàn toàn trong suốt)

    • Position = 0.5, 0, 0.35, 0 (giữa theo chiều ngang và 35% từ trên cùng của container)

    • Size = 0.8, 0, 0.1, 0 (80% chiều rộng của container và 10% chiều cao của nó)

      Khung trống được chèn để chứa các yếu tố thanh trượt.
  3. Chèn một UIListLayout mới vào EffectsVolumeSlider. Bộ điều chỉnh bố cục này là một cách mạnh mẽ để tự động sắp xếp các GuiObjects anh em thành các hàng ngang hoặc cột dọc trong container cha của chúng, bao gồm khả năng áp dụng các khái niệm flex.

    Cửa sổ Explorer hiển thị một UIListLayout mới được chèn vào khung EffectsVolumeSlider.
  4. Đặt các thuộc tính sau cho UIListLayout mới:

    • Padding = 0.06, 0 (6% khoảng cách giữa các yếu tố trong danh sách)
    • FillDirection = Horizontal (sắp xếp các yếu tố từ trái sang phải)
    • HorizontalFlex = Fill (thay đổi kích thước các yếu tố theo chiều ngang để lấp đầy toàn bộ container cha, ghi đè kích thước đã định nghĩa của chúng)
    • VerticalAlignment = Center (căn chỉnh các yếu tố theo chiều dọc ở giữa)

Biểu tượng thanh trượt

Một biểu tượng đơn giản bao gồm một nốt âm thanh và biểu tượng "bùng nổ" giúp người chơi nhận biết mục đích của thanh trượt khi họ mở menu cài đặt.

Biểu tượng chỉ ra mục đích của thanh trượt trong menu cài đặt.
  1. Chèn một ImageLabel vào khung EffectsVolumeSlider và đổi tên thành Icon. Biểu tượng này sẽ giúp người chơi hiểu được khía cạnh nào của trò chơi mà thanh trượt điều khiển.

    Cửa sổ Explorer hiển thị một ImageLabel được chèn vào khung EffectsVolumeSlider.
  2. Với Icon được chọn, đặt các thuộc tính sau:

    • BackgroundTransparency = 1 (hoàn toàn trong suốt)
    • Size = 2.5, 0, 2.5, 0 (250% chiều cao của khung cha khi tỷ lệ khung hình được ràng buộc)
    • Image = rbxassetid://90019827067389 (ID tài sản của nốt âm thanh và biểu tượng "bùng nổ")
  3. Chèn một UIAspectRatioConstraint vào Icon và để các thuộc tính của nó ở mặc định (tỷ lệ 1:1 giữa chiều rộng và chiều cao).

    Cửa sổ Explorer hiển thị một UIAspectRatioConstraint được chèn vào ImageLabel. Biểu tượng đã hoàn thiện trong menu cài đặt.

Khung phạm vi

Ngay bên phải của biểu tượng, phần tương tác của thanh trượt nên được chứa trong một Frame khác.

Kích thước và vị trí mục tiêu của phần tương tác của thanh trượt.
  1. Chèn một Frame mới vào khung EffectsVolumeSlider và đổi tên thành SliderFrame. Lưu ý rằng nó phải là một anh em trực tiếp của bộ điều chỉnh UIListLayout.

    Cửa sổ Explorer hiển thị một khung con được chèn vào khung EffectsVolumeSlider.
  2. Với SliderFrame được chọn, đặt các thuộc tính sau:

  3. Chèn các bộ điều chỉnh sau vào SliderFrame:

    Khung thanh trượt được định vị bên phải biểu tượng.

Tay cầm tương tác

Với container thanh trượt đã được xây dựng, bạn có thể tạo một tay cầm có thể kéo cho người chơi tương tác trong quá trình chơi.

Tay cầm thanh trượt tương tác được định vị trong khung phạm vi.
  1. Chèn một Frame mới vào container SliderFrame và đổi tên thành Handle.

    Cửa sổ Explorer hiển thị một khung con được chèn vào khung SliderFrame và đổi tên thành Handle.
  2. Với Handle được chọn, đặt các thuộc tính sau:

    • AnchorPoint = 0.5 (neo ở giữa)
    • Position = 0.5, 0, 0.5, 0 (giữa theo chiều ngang và chiều dọc của khung cha)
    • Size = 1.2, 0, 1.2, 0 (120% chiều cao của khung cha khi tỷ lệ khung hình được ràng buộc)
    • ZIndex = 3 (đặt tay cầm ở phía trước các yếu tố thanh trượt khác)
  3. Chèn các bộ điều chỉnh sau vào Handle:

  4. Chèn một đối tượng UIDragDetector vào Handle. Đối tượng tiện lợi này giúp dễ dàng và khuyến khích tương tác với các yếu tố giao diện người dùng 2D.

    Cửa sổ Explorer hiển thị một UIDragDetector được chèn vào khung Handle.
  5. Đặt các thuộc tính sau cho UIDragDetector mới:

  6. Để đảm bảo phạm vi kéo tuyến tính của tay cầm được giới hạn trong container của nó, liên kết thuộc tính BoundingUI của nó với container SliderFrame:

    1. Nhấp vào thuộc tính BoundingUI của nó trong cửa sổ Properties.
    2. Quay lại cửa sổ Explorer, nhấp vào cha của tay cầm SliderFrame.
    Sơ đồ hiển thị quy trình liên kết thuộc tính BoundingUI của detector với container SliderFrame.

    Liên kết thuộc tính BoundingUI giờ đây phản ánh container SliderFrame:

    Cửa sổ Properties hiển thị thuộc tính BoundingUI của detector được liên kết với container SliderFrame.

Nếu bạn thử nghiệm trò chơi bây giờ, bạn sẽ có thể kéo tay cầm sang trái và phải trong container cha của nó:

Điền bên trong

Để chỉ ra rõ ràng hơn rằng thanh trượt điều khiển một phạm vi từ 0% đến 100%, bạn có thể thêm một phần điền bên trong vào bên trái của container sẽ đồng bộ với vị trí biến đổi của tay cầm.

Phần điền bên trong của thanh trượt được chèn vào SliderFrame.
  1. Chèn một Frame mới vào container SliderFrame và đổi tên thành InnerFill.

    Cửa sổ Explorer hiển thị một khung con được chèn vào khung SliderFrame và đổi tên thành InnerFill.
  2. Đặt các thuộc tính sau cho khung InnerFill:

    • AnchorPoint = 0, 0.5 (cạnh trái và giữa theo chiều dọc)
    • BackgroundColor3 = [0, 150, 255] (màu xanh phù hợp với tay cầm của thanh trượt)
    • BackgroundTransparency = 0.35 (65% mờ)
    • Position = 0, 0, 0.5, 0
    • Size = 0.5, 0, 1, 0 (50% chiều rộng và 100% chiều cao của khung cha)
    • ZIndex = 2 (đặt ở phía trước phần điền/viền của khung cha)
  3. Để phù hợp với hình dạng "viên thuốc" của container cha SliderFrame, chèn một bộ điều chỉnh UICorner và đặt thuộc tính CornerRadius của nó thành 0.5, 0.

    Cửa sổ Explorer hiển thị một bộ điều chỉnh UICorner được chèn vào khung InnerFill.
    Cửa sổ Properties hiển thị các giá trị mong đợi cho bộ điều chỉnh UICorner mới.
    Khung InnerFill được tạo kiểu với nền xanh và các góc tròn.

Nhân bản thanh trượt

Với thanh trượt đầu tiên đã được xây dựng, bạn có thể dễ dàng nhân bản nó và thay đổi một số khía cạnh hình ảnh để chỉ ra một mục đích khác, trong trường hợp này là mức âm lượng của âm thanh nền được biểu thị bằng một biểu tượng của các nốt nhạc.

Vị trí mục tiêu của thanh trượt âm thanh nền.
  1. Chọn đối tượng EffectsVolumeSlider đã hoàn thành.

    Cửa sổ Explorer hiển thị EffectsVolumeSlider đã hoàn thành được chọn.
  2. Nhân bản nó (CtrlD hoặc D) và sau đó đổi tên bản sao thành BackgroundVolumeSlider.

    Cửa sổ Explorer hiển thị thanh trượt đã nhân bản được đổi tên thành BackgroundVolumeSlider.
  3. Thay đổi Position của bản sao thành 0.5, 0, 0.7, 0 để di chuyển nó xuống dưới thanh trượt đầu tiên.

    BackgroundVolumeSlider được định vị bên dưới EffectsVolumeSlider.
  4. Mở rộng nhánh cấp cao của BackgroundVolumeSlider, chọn nhãn hình Icon, và thay đổi thuộc tính Image của nó thành rbxassetid://101125859760167 (ID tài sản của biểu tượng với các nốt nhạc).

    Cửa sổ Explorer hiển thị nhãn Icon trong BackgroundVolumeSlider.
    Cửa sổ Properties hiển thị các giá trị mong đợi cho nhãn Icon.
    BackgroundVolumeSlider với hình ảnh biểu tượng đã thay đổi.
  5. Mở rộng nhánh SliderFrameHandle, chọn bộ điều chỉnh UIStroke bên trong, và đặt thuộc tính Color của nó thành [255, 0, 125] (màu hồng).

    Cửa sổ Explorer hiển thị bộ điều chỉnh UIStroke bên trong tay cầm của BackgroundVolumeSlider.
    Cửa sổ Properties hiển thị các giá trị mong đợi cho bộ điều chỉnh UIStroke.
    BackgroundVolumeSlider với hình ảnh biểu tượng đã thay đổi.
  6. Chọn khung InnerFill bên trong SliderFrame và thay đổi thuộc tính BackgroundColor3 của nó thành màu hồng giống như ([255, 0, 125]).

    Cửa sổ Explorer hiển thị khung InnerFill bên trong container SliderFrame của BackgroundVolumeSlider.
    Cửa sổ Properties hiển thị các giá trị mong đợi cho khung InnerFill.
    BackgroundVolumeSlider với màu InnerFill đã thay đổi.

Tạo nút đóng

Yếu tố cuối cùng của menu cài đặt là một nút đóng cung cấp cho người chơi một đầu vào bổ sung để đóng menu (nút SettingsButton ở giữa trên sẽ phục vụ cùng một mục đích).

Menu cài đặt với nút đóng được chỉ định ở góc trên bên phải.
  1. Chèn một ImageButton mới vào container SettingsMenu và đổi tên thành CloseButton.

    Cửa sổ Explorer hiển thị một ImageButton mới được chèn vào SettingsMenu và đổi tên thành CloseButton. Nút ImageButton trống được định vị ở góc trên bên trái của menu cài đặt.
  2. Với CloseButton được chọn, đặt các thuộc tính sau:

    • AnchorPoint = 1, 0 (góc trên bên phải)
    • BackgroundTransparency = 1 (hoàn toàn trong suốt)
    • Position = 1, -10, 0, 10 (10 pixel từ góc trên bên phải)
    • Size = 0.15, 0, 0.15, 0 (15% chiều cao của khung khi tỷ lệ khung hình được ràng buộc)
    • Image = rbxassetid://5577404210 (ID tài sản của biểu tượng nút đóng)
    • ImageTransparency = 0.25 (75% mờ)
  3. Chèn một UIAspectRatioConstraint vào nút với các thuộc tính mặc định (tỷ lệ 1:1 giữa chiều rộng và chiều cao).

    Cửa sổ Explorer hiển thị một UIAspectRatioConstraint được chèn vào nút CloseButton. Nút đóng đã hoàn thiện ở góc trên bên phải của menu cài đặt.

Tạo các module điều khiển

Một thiết lập module điều khiển có thể mở rộng giúp quản lý UI tương tác dễ dàng hơn so với các script riêng lẻ được đặt trong mỗi đối tượng. ModuleScripts tạo điều kiện cho chức năng mở rộng này bằng cách cho phép bạn tái sử dụng mã giữa các script ở hai bên của ranh giới client-server hoặc cùng một bên của ranh giới.

Bộ điều khiển đối tượng có trạng thái

Module bộ điều khiển đối tượng có trạng thái sau cho phép bạn gán hành vi cho các đối tượng UI như SettingsButtonSettingsMenu, và dễ dàng bật/tween giữa các trạng thái khác nhau. Để tạo module:

  1. Chèn một ModuleScript vào container ReplicatedStorage và đổi tên thành StatefulObjectController.

    Cửa sổ Explorer hiển thị module StatefulObjectController bên trong container ReplicatedStorage.
  2. Dán mã sau vào bên trong module:

    StatefulObjectController
    local TweenService = game:GetService("TweenService")
    local StatefulObjectController = {}
    StatefulObjectController.__index = StatefulObjectController
    export type StateName = string
    export type State = {
    transition: TweenInfo,
    properties: { [string]: any },
    }
    function StatefulObjectController.hydrate(props: {
    object: Instance,
    states: { [StateName]: State },
    initialStateName: StateName
    })
    local object, states, initialStateName = props.object, props.states, props.initialStateName
    local self = setmetatable({
    states = states,
    currentStateName = initialStateName,
    tweens = {},
    }, StatefulObjectController)
    -- Tạo tweens để tái sử dụng nhằm tránh việc tạo tweens mới mỗi khi trạng thái thay đổi
    for stateName, state in states do
    self.tweens[stateName] = TweenService:Create(object, state.transition, state.properties)
    end
    self:setState(self.currentStateName)
    return self
    end
    function StatefulObjectController:setState(stateName: StateName)
    local stateTween: Tween = self.tweens[stateName]
    if not stateTween then
    warn(string.format("Đã cố gắng đặt %s thành trạng thái không xác định '%s'", self.object:GetFullName(), stateName))
    return
    end
    self.currentStateName = stateName
    -- Đảm bảo rằng các tweens khác không xung đột
    for _, tween in self.tweens do
    tween:Cancel()
    end
    stateTween:Play()
    end
    return StatefulObjectController
    DòngMục đích
    610Định nghĩa và xuất các loại Luau để cải thiện tự động hoàn thành và linting khi sử dụng module này.
    1233Hàm được sử dụng để khởi tạo và gán hành vi cho một đối tượng UI có trạng thái, chấp nhận một GuiObject làm object, một bảng các trạng thái và dữ liệu TweenInfo tương ứng của chúng, và một tên trạng thái ban đầu. Bên trong hàm này, các dòng 2628 xây dựng Tweens cho mỗi trạng thái, và dòng 30 gọi hàm setState() của module để đặt đối tượng vào trạng thái ban đầu.
    3550Hàm được sử dụng để đặt/thay đổi trạng thái của một đối tượng có trạng thái. Bên trong hàm, các dòng 42 đặt currentStateName của đối tượng thành trạng thái đang được đặt, các dòng 4547 hủy bỏ bất kỳ tweens đang chạy để ngăn chặn xung đột, và dòng 49 thực thi tween của trạng thái.

Bộ điều khiển thanh trượt

Một module bổ sung khởi tạo và điều khiển hai thanh trượt âm lượng. Nó cũng cho phép bạn kết nối một hàm callback với mỗi thanh trượt để phát hiện tương tác của người chơi với thanh trượt và áp dụng các thay đổi mong muốn trong trò chơi.

  1. Chèn một ModuleScript vào container ReplicatedStorage và đổi tên thành SliderController.

    Cửa sổ Explorer hiển thị module SliderController bên trong container ReplicatedStorage.
  2. Dán mã sau vào bên trong module:

    SliderController
    local SliderController = {}
    SliderController.__index = SliderController
    export type Value = number
    export type OnChanged = (Value) -> ()
    function SliderController.hydrate(props: {
    object: Instance,
    onChanged: OnChanged,
    initialValue: Value?
    })
    local object, onChanged, initialValue = props.object, props.onChanged, props.initialValue
    local handle = object:FindFirstChild("Handle", true)
    if not handle then
    warn(string.format("Đã cố gắng khởi tạo thanh trượt %s nhưng không thể tìm thấy Handle", object:GetFullName()))
    end
    local innerFill = object:FindFirstChild("InnerFill", true)
    if not innerFill then
    warn(string.format("Đã cố gắng khởi tạo thanh trượt %s nhưng không thể tìm thấy InnerFill", object:GetFullName()))
    end
    local dragDetector = handle:FindFirstChildWhichIsA("UIDragDetector")
    if not dragDetector then
    warn(string.format("Đã cố gắng khởi tạo thanh trượt %s nhưng không thể tìm thấy UIDragDetector", object:GetFullName()))
    end
    local self = setmetatable({
    handle = handle,
    innerFill = innerFill,
    dragDetector = dragDetector,
    value = initialValue or 0.5,
    onChanged = onChanged,
    }, SliderController)
    -- Đặt giá trị ban đầu
    self:setValue(self.value)
    -- Kết nối detector với thao tác của người chơi
    self.dragConnection = dragDetector.DragContinue:Connect(function()
    self:setValue(handle.Position.X.Scale)
    end)
    return self
    end
    function SliderController:setValue(value: Value)
    local clampedValue = math.clamp(value, 0, 1)
    self.value = clampedValue
    -- Cập nhật vị trí tay cầm và kích thước khung bên trong để khớp
    self.handle.Position = UDim2.fromScale(clampedValue, 0.5)
    self.innerFill.Size = UDim2.fromScale(clampedValue, 1)
    -- Chạy callback của người dùng với giá trị mới nhất
    local changeSuccess, changeResult = pcall(self.onChanged, clampedValue)
    if not changeSuccess then
    warn("Lỗi trong callback thanh trượt:", changeResult)
    end
    end
    return SliderController
    DòngMục đích
    746Hàm được sử dụng để khởi tạo và gán hành vi cho một yếu tố thanh trượt, chấp nhận Frame cha của thanh trượt làm object, một hàm callback onChanged để xử lý các thay đổi của thanh trượt, và một giá trị ban đầu cho vị trí tay cầm của thanh trượt. Bên trong hàm, các dòng 1427 xác nhận rằng các yếu tố tay cầm, điền bên trong, và UIDragDetector tồn tại. Dòng 38 gọi hàm setValue() của module và các dòng 4143 kết nối sự kiện DragContinue của detector với hàm setValue() của module (xem dòng tiếp theo để biết thêm chi tiết).
    4861Hàm được sử dụng để đặt giá trị của thanh trượt. Bên trong hàm, các dòng 5354 đảm bảo rằng vị trí tay cầm và kích thước khung bên trong được đồng bộ, và dòng 57 truyền giá trị đã thay đổi đến hàm callback để bạn có thể sử dụng giá trị theo nhu cầu.

Tạo script cài đặt

Với nút cài đặtmenu cài đặt đã hoàn thiện, bạn có thể kết nối mọi thứ lại với nhau bằng một script duy nhất sử dụng các module điều khiển.

  1. Chèn một LocalScript mới vào HUDContainer và đổi tên thành SettingsScript để mô tả mục đích của nó. Lưu ý rằng script này nên ở cùng cấp (anh em) với SettingsMenuSettingsButton, các đối tượng UI cấp cao mà nó sẽ quản lý.

    Cửa sổ Explorer hiển thị script SettingsScript bên trong container HUDContainer.
  2. Dán mã sau vào bên trong script:

    SettingsScript
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local SoundService = game:GetService("SoundService")
    local SliderController = require(ReplicatedStorage.SliderController)
    local StatefulObjectController = require(ReplicatedStorage.StatefulObjectController)
    local HUDContainer = script.Parent
    -- Khởi tạo nút cài đặt
    local settingsButton = StatefulObjectController.hydrate({
    object = HUDContainer:FindFirstChild("SettingsButton"),
    states = {
    menuOpen = {
    transition = TweenInfo.new(0.5, Enum.EasingStyle.Exponential, Enum.EasingDirection.Out),
    properties = {
    Rotation = 45,
    },
    },
    menuClosed = {
    transition = TweenInfo.new(0.5, Enum.EasingStyle.Exponential, Enum.EasingDirection.Out),
    properties = {
    Rotation = 0,
    },
    },
    },
    initialStateName = "menuClosed"
    })
    -- Khởi tạo khung menu cài đặt
    local settingsMenu = StatefulObjectController.hydrate({
    object = HUDContainer:FindFirstChild("SettingsMenu"),
    states = {
    menuOpen = {
    transition = TweenInfo.new(0.5, Enum.EasingStyle.Bounce, Enum.EasingDirection.Out),
    properties = {
    Position = UDim2.fromScale(0.5, 0.5),
    Visible = true,
    },
    },
    menuClosed = {
    transition = TweenInfo.new(0),
    properties = {
    Position = UDim2.fromScale(0.5, 0.4),
    Visible = false,
    },
    },
    },
    initialStateName = "menuClosed"
    })
    -- Khởi tạo thanh trượt âm lượng hiệu ứng
    local effectsAudio = SoundService:FindFirstChild("Effects")
    local effectsVolumeSlider = SliderController.hydrate({
    object = HUDContainer:FindFirstChild("EffectsVolumeSlider", true),
    initialValue = effectsAudio and effectsAudio.Volume or 0.5,
    onChanged = function(value: SliderController.Value)
    if effectsAudio then
    effectsAudio.Volume = value
    end
    end,
    })
    -- Khởi tạo thanh trượt âm lượng nền
    local backgroundAudio = SoundService:FindFirstChild("Background")
    local backgroundVolumeSlider = SliderController.hydrate({
    object = HUDContainer:FindFirstChild("BackgroundVolumeSlider", true),
    initialValue = backgroundAudio and backgroundAudio.Volume or 0.5,
    onChanged = function(value: SliderController.Value)
    if backgroundAudio then
    backgroundAudio.Volume = value
    end
    end,
    })
    -- Kết nối các nút với tương tác của người chơi
    HUDContainer:FindFirstChild("SettingsButton").Activated:Connect(function()
    local targetState = if settingsButton.currentStateName == "menuClosed"
    then "menuOpen"
    else "menuClosed"
    settingsButton:setState(targetState)
    settingsMenu:setState(targetState)
    end)
    HUDContainer:FindFirstChild("CloseButton", true).Activated:Connect(function()
    settingsButton:setState("menuClosed")
    settingsMenu:setState("menuClosed")
    end)
  3. Tham khảo các phần sau để khám phá cách script sử dụng các module điều khiển.

    Các dòng 10-27 khởi tạo và gán hành vi cho nút cài đặt như sau:

    DòngMục đích
    1011Một tham chiếu cục bộ settingsButton được khai báo và khởi tạo với hàm StatefulObjectController.hydrate(), và nút SettingsButton bên trong HUDContainer được tham chiếu làm đối tượng để khởi tạo.
    1225Một bảng states được truyền vào với hai trạng thái duy nhất, menuOpenmenuClosed. Mỗi trạng thái chứa một chuyển tiếp để khai báo (thông qua một TweenInfo) cách mà trạng thái cụ thể sẽ đạt được các thuộc tính mục tiêu được định nghĩa trong bảng properties. Trong trường hợp này, menuOpen khai báo một thay đổi trạng thái thành 45° cho Rotation của nút với một tween Exponential trong ½ giây, trong khi menuClosed hiệu quả khôi phục nút về độ xoay mặc định là 0.
    26Trạng thái ban đầu của nút được đặt thành menuClosed (điều này có thể được đặt thành bất kỳ tên trạng thái nào trong bảng states).

    Ở phía dưới trong script (các dòng 76-86), các nút được kết nối với tương tác của người chơi để kích hoạt các thay đổi trạng thái UI:

    DòngMục đích
    7682SettingsButton được kết nối với sự kiện Activated của lớp GuiButton để gọi một hàm ẩn danh. Bên trong hàm ẩn danh, các dòng 7779 chuyển đổi một biến targetState giữa menuOpenmenuClosed. Dòng 80 sau đó gọi setState() để đặt trạng thái của nút thành targetState và dòng 81 làm điều tương tự với SettingsMenu để nó mở hoặc đóng cùng với việc kích hoạt SettingsButton.
    8386CloseButton được kết nối với sự kiện Activated để gọi một hàm ẩn danh mà đặt trạng thái của cả SettingsButtonSettingsMenu thành menuClosed.

    Các dòng 30-49 khởi tạo và gán hành vi cho menu cài đặt như sau:

    DòngMục đích
    3031Một tham chiếu cục bộ settingsMenu được khai báo và khởi tạo với hàm StatefulObjectController.hydrate() và khung SettingsMenu bên trong HUDContainer được tham chiếu làm đối tượng để khởi tạo.
    3246Tương tự như nút cài đặt, một bảng states được truyền vào với hai trạng thái duy nhất, menuOpenmenuClosed. Ở đây, menuOpen khai báo một thay đổi trạng thái thành UDim2.fromScale(0.5, 0.5) cho Position của khung với một tween Bounce trong ½ giây, cũng như một trạng thái Visibletrue. Ngược lại, menuClosed khai báo một thay đổi trạng thái vị trí thành UDim2.fromScale(0.5, 0.4)Visible thành false, nhưng TweenInfo với thời gian 0 ở dòng 41 hiệu quả làm cho thay đổi trạng thái xảy ra ngay lập tức.
    48Trạng thái ban đầu của khung được đặt thành menuClosed.

    Ở phía dưới trong script (các dòng 76-86), menu cài đặt được liên kết với tương tác của người chơi:

    DòngMục đích
    81Đặt cùng một targetState cho SettingsMenu để đồng bộ với việc kích hoạt SettingsButton.
    85Đặt trạng thái của SettingsMenu thành menuClosed khi CloseButton được kích hoạt.

    Các dòng 51-73 khởi tạo và gán hành vi cho EffectsVolumeSliderBackgroundVolumeSlider như sau:

    DòngMục đích
    52Đặt một tham chiếu cục bộ đến SoundGroup Effects bên trong SoundService. Một SoundGroup cho phép bạn liên kết nhiều Sounds và điều khiển âm lượng của mọi âm thanh trong nhóm thông qua thuộc tính Volume của nhóm.
    5354Một tham chiếu cục bộ effectsVolumeSlider được khai báo và khởi tạo với hàm SliderController.hydrate() và khung EffectsVolumeSlider bên trong HUDContainer ⟩ SettingsMenu được tham chiếu làm đối tượng để khởi tạo. Lưu ý rằng tham số thứ hai của true cho FindFirstChild() cho biết phương thức này sẽ tìm kiếm đệ quy xuống nhánh HUDContainer để xác định EffectsVolumeSlider.
    55Giá trị ban đầu của thanh trượt được đặt thành Volume hiện tại của nhóm Effects, hoặc 0.5 như một phương án dự phòng.
    5660Thiết lập hàm callback để áp dụng các thay đổi giá trị thanh trượt cho âm lượng của nhóm âm thanh Effects.
    6473Về cơ bản giống như các dòng 52-61, ngoại trừ việc khởi tạo khung BackgroundVolumeSlider bên trong HUDContainer ⟩ SettingsMenu và áp dụng các thay đổi giá trị thanh trượt cho âm lượng của nhóm âm thanh Background.

Với SettingsScript đã được thiết lập, trò chơi giờ đây cung cấp một ví dụ UI tương tác hoàn toàn hoạt động liên kết một tập hợp các đối tượng UI liên quan với tương tác của người chơi.

©2026 Roblox Corporation. Roblox, logo Roblox và Powering Imagination là các nhãn hiệu đã đăng ký và chưa đăng ký của chúng tôi tại Hoa Kỳ và các quốc gia khác.