คู่มือการใช้งานระดับกลาง

สร้าง UI แบบอินเทอร์แอกทีฟ

*เนื้อหานี้แปลโดยใช้ AI (เวอร์ชัน Beta) และอาจมีข้อผิดพลาด หากต้องการดูหน้านี้เป็นภาษาอังกฤษ ให้คลิกที่นี่

HUD (Heads-Up Display) ในประสบการณ์ของคุณมักจะแสดงองค์ประกอบ UI ที่ไม่โต้ตอบเช่นมิเตอร์สุขภาพที่แสดงใน สร้างมิเตอร์ HUD นอกจากนี้ แทบทุกประสบการณ์ต้องการ UI เชิงโต้ตอบ เช่นปุ่มที่ตอบสนองต่อการกระตุ้นของผู้เล่น มีการเคลื่อนไหวเมื่อเปิดใช้งาน แอนิเมชั่นเมนูที่ไล่เข้า/ออกพร้อมกับการควบคุมเชิงโต้ตอบอื่น ๆ เป็นต้น

มุมมองในเกมแสดงปุ่มตั้งค่าและเมนูตั้งค่าพร้อมกับตัวเลื่อนเสียง.

ใช้ UI Fundamentals - HUD Meter เป็นจุดเริ่มต้นและ UI Fundamentals - Interactivity เป็นเอกสารอ้างอิงที่เสร็จสิ้นบทช่วยสอนนี้แสดงให้เห็นถึง:

  • วิธีการจัดตำแหน่งปุ่มตั้งค่าที่ขอบด้านบนของหน้าจอ
  • การออกแบบเมนูตั้งค่าที่มีตัวเลื่อนที่สามารถลากได้แบบเชิงโต้ตอบ
  • การใช้งาน ModuleScripts เพื่อสร้างโมดูล "ตัวควบคุม" สำหรับการควบคุม UI ที่สามารถขยายได้ด้วยการประกาศสถานะ
  • วิธีเชื่อมต่อปุ่มกับการกระตุ้นของผู้เล่นเพื่อเปิด/ปิดเมนูตั้งค่า
  • วิธีเชื่อมต่อ UI sliders ที่ลากได้เพื่อตั้งค่าระดับเสียงของเอฟเฟกต์เสียงและบรรยากาศพื้นหลังแยกจากกัน

เปิดใช้งานตัวจำลองอุปกรณ์

ตามที่กล่าวไว้ใน สร้างมิเตอร์ HUD โทรศัพท์และแท็บเล็ตมีพื้นที่หน้าจอที่น้อยที่สุด ดังนั้นจึงเป็นสิ่งสำคัญที่องค์ประกอบ UI ของคุณจะต้องพอดีกับหน้าจอขนาดเล็กกว่าและเห็นได้ชัดเจนสำหรับผู้เล่น หากคุณยังไม่ได้ทำ โปรดเปิดใช้งาน Device Emulator ใน Studio:

  1. เปิดเทมเพลต UI Fundamentals - HUD Meter ใน Studio.

  2. จากเมนู Test ของ Studio ให้เปิด Device Emulator.

  3. จากแถบโดยตรงด้านบนมุมมองหลักให้เลือกอีมูเลเตอร์โทรศัพท์ เช่น iPhone X หรือ Samsung Galaxy A51 จากนั้นตั้งค่าขนาดมุมมองเป็น Fit to Window เพื่อใช้พื้นที่สูงสุดใน Studio.

    ตัวเลือกการตั้งค่าตัวจำลองอุปกรณ์ระบุที่ด้านบนของหน้าต่างมุมมอง.

สร้างปุ่มตั้งค่า

GuiButtons เป็นองค์ประกอบอินเทอร์เฟซผู้ใช้ที่มีฟังก์ชันการทำงานในตัว เช่น เหตุการณ์ Activated แบบหลายแพลตฟอร์มซึ่งจะทำงานเมื่อมีการคลิกหรือแตะปุ่ม GuiButton ชนิดมีก 2 รูปแบบ TextButton และ ImageButton โดยบทช่วยสอนนี้ใช้ ImageButton รูปทรง "เกียร์" เพื่อเปิดหรือปิดเมนูตั้งค่า

องค์ประกอบ Roblox ที่ใช้สำหรับปุ่มตั้งค่า.

ในการสร้างปุ่มตั้งค่า:

  1. ในหน้าต่าง Explorer ให้ค้นหา HUDContainer ภายใน StarterGui.

    หน้าต่าง Explorer แสดงให้เห็นว่าเลือก HUDContainer.
  2. แทรก ImageButton ลงใน HUDContainer และเปลี่ยนชื่อเป็น SettingsButton.

    หน้าต่าง Explorer แสดงให้เห็นว่ามีการแทรก ImageButton ใหม่และเปลี่ยนชื่อเป็น SettingsButton. ImageButton ใหม่ในมุมมอง.
  3. เมื่อเลือกปุ่มใหม่แล้วให้ตั้งค่าในหน้าต่าง Properties ดังนี้:

    • AnchorPoint = 0.5, 0.25 (กลางทางด้านขวาและด้านแนวตั้งอันดับที่หนึ่ง)
    • BackgroundTransparency = 1 (โปร่งใสเต็มที่)
    • Position = 0.5, 0, 0, 0 (จัดตำแหน่งกลางด้านบน)
    • Size = 0.1, 0, 0.1, 0 (10% ของความสูงหน้าจอเมื่อจำกัดอัตราส่วน)
    • Image = rbxassetid://104919049969988 (ID ของทรัพย์สินสัญลักษณ์ "เกียร์")
  4. แทรก UIAspectRatioConstraint ลงในปุ่มด้วยค่าเริ่มต้น (อัตราส่วน 1:1 ความกว้างต่อความสูง).

    หน้าต่าง Explorer แสดงให้เห็นว่ามีการแทรก UIAspectRatioConstraint ลงในปุ่ม SettingsButton.
  5. เพื่อจำกัดความสูงพิกเซลสูงสุดของปุ่มให้แทรก UISizeConstraint และตั้งค่า MaxSize เป็น inf, 44.

    หน้าต่าง Explorer แสดงให้เห็นว่ามีการแทรก UISizeConstraint ใหม่ลงในปุ่ม SettingsButton.
    หน้าต่าง Properties แสดงค่าที่คาดหวังสำหรับ UISizeConstraint ใหม่.
    ปุ่มตั้งค่าสุดท้ายในกลางด้านบนของหน้าจอ.

สร้างเมนูตั้งค่า

ปุ่ม ตั้งค่า ใหม่จะต้องมีการเขียนสคริปต์เพื่อเป็นการเปิดและปิดเมนูตั้งค่า ซึ่งจะให้ผู้เล่นเข้าถึงการตั้งค่าหรือข้อมูลอื่นๆ ได้ตามที่ต้องการ ในบทช่วยสอนนี้ เมนูจะมีตัวเลื่อนแบบอินเทอร์แอกทีฟเพื่อตั้งค่าระดับเสียงของเสียงพื้นหลังและเอฟเฟกต์เสียงโดยแยกกัน

ส่วนประกอบพื้นฐานที่ใช้สำหรับเมนูตั้งค่า.

สร้างกรอบหลัก

ตามที่ได้กล่าวไว้ใน สร้างมิเตอร์ HUD Frame ทำหน้าที่เป็นตัวเก็บสำหรับวัตถุ UI อื่น ๆ เมนูตั้งค่าทั้งหมดจะถูกสร้างขึ้นจากกรอบหลักเดียว ทำให้จัดการได้ง่ายในฐานะวัตถุที่มีสถานะซึ่งตอบสนองต่อการป้อนข้อมูลแตกต่างกันไปตามสถานะปัจจุบัน

  1. แทรก Frame ลงใน HUDContainer และเปลี่ยนชื่อเป็น SettingsMenu.

    หน้าต่าง Explorer แสดงให้เห็นว่ามีการแทรกกรอบใหม่และเปลี่ยนชื่อเป็น SettingsMenu.
  2. เมื่อเลือก SettingsMenu แล้วให้ตั้งค่าให้เป็นไปตามนี้:

    • AnchorPoint = 0.5 (จุดยึดกลาง)
    • BackgroundColor3 = 30, 30, 60 (สีน้ำเงินเข้ม)
    • BackgroundTransparency = 0.25 (โปร่งใส 75%)
    • Position = 0.5, 0, 0.5, 0 (กลางของหน้าจอ)
    • Size = 0.75, 0, 0.75, 0 (75% ของความกว้าง/ความสูงของพื้นที่หน้าจอที่ตัดออก)
    กรอบถูกปรับตำแหน่ง ขนาด และสไตล์พร้อมพื้นหลังสีน้ำเงินเข้มโปร่งใส.
  3. แทรก UIAspectRatioConstraint ลงใน SettingsMenu และตั้งค่า AspectRatio เป็น 2.5. (อัตราส่วนกว้างต่อสูง 2.5:1).

    หน้าต่าง Explorer แสดงให้เห็นว่ามีการแทรก UISizeConstraint ใหม่ลงในกรอบ SettingsMenu.
    หน้าต่าง Properties แสดงค่าที่คาดหวังสำหรับ UISizeConstraint ใหม่.
  4. แทรกตัวปรับแต่ง UICorner ลงใน SettingsMenu และตั้งค่า CornerRadius เป็น 0.1, 0.

    หน้าต่าง Explorer แสดงการแทรก UICorner ใหม่ลงในกรอบ SettingsMenu.
    หน้าต่าง Properties แสดงค่าที่คาดหวังสำหรับตัวปรับ UICorner ใหม่.
  5. เพื่อจำกัดความกว้างและความสูงพิกเซลของ SettingsMenu ให้แทรก UISizeConstraint ตั้งค่า MaxSize เป็น 800, inf และ MinSize เป็น 350, 0.

    หน้าต่าง Explorer แสดงให้เห็นว่ามีการแทรก UISizeConstraint ใหม่ลงในกรอบ SettingsMenu.
    หน้าต่าง Properties แสดงค่าที่คาดหวังสำหรับ UISizeConstraint ใหม่.
    กรอบที่ตกแต่งด้วยมุมโค้ง.

สร้างตัวเลื่อน

เพื่อให้ผู้เล่นสามารถปรับระดับเสียงได้ เมนูตั้งค่าจะมีตัวเลื่อน slider widgets ที่สามารถลากได้ โดยใช้ UIDragDetector ซึ่งเป็นวัตถุที่สะดวกในการทำให้เกิดการโต้ตอบกับองค์ประกอบ UI 2D


ในการสร้างตัวเก็บสำหรับตัวเลื่อนแรก:

  1. แทรก Frame ใหม่ลงใน SettingsMenu และเปลี่ยนชื่อเป็น EffectsVolumeSlider.

    หน้าต่าง Explorer แสดงให้เห็นว่ามีการแทรกกรอบใหม่ลงในกรอบ SettingsMenu และเปลี่ยนชื่อเป็น EffectsVolumeSlider.
  2. เมื่อเลือกกรอบ EffectsVolumeSlider แล้วให้ตั้งค่าให้เป็นไปตามนี้:

    • AnchorPoint = 0.5 (จุดยึดกลาง)
    • BackgroundTransparency = 1 (โปร่งใสเต็มที่)
    • Position = 0.5, 0, 0.35, 0 (กลางระยะทางแนวนอนและ 35% จากด้านบนของตัวเก็บ)
    • Size = 0.8, 0, 0.1, 0 (80% ของความกว้างของตัวเก็บและ 10% ของความสูง)
    กรอบว่างถูกแทรกเพื่อเก็บองค์ประกอบตัวเลื่อน.
  3. แทรก UIListLayout ใหม่ลงใน EffectsVolumeSlider ตัวปรับเลย์เอาต์นี้เป็นวิธีที่มีประสิทธิภาพในการเรียงลำดับ GuiObjects ที่เป็นพี่น้องกันไปในแถวแนวนอนหรือคอลัมน์แนวตั้งในตัวเก็บหลักของพวกเขา รวมทั้งความสามารถในการใช้แนวคิด flex.

    หน้าต่าง Explorer แสดงให้เห็นว่ามีการแทรก UIListLayout ใหม่ลงในกรอบ EffectsVolumeSlider.
  4. ตั้งค่าคุณสมบัติต่อไปนี้สำหรับ UIListLayout ใหม่:

    • Padding = 0.06, 0 (ช่องว่างระหว่างองค์ประกอบในรายการ 6%)
    • FillDirection = Horizontal (การจัดเรียงองค์ประกอบจากซ้ายไปขวา)
    • HorizontalFlex = Fill (ปรับขนาดองค์ประกอบให้กว้างขึ้นเพื่อเติมเต็มตัวเก็บหลักทั้งหมด โดยยกเลิกความกว้างที่กำหนด)
    • VerticalAlignment = Center (จัดเรียงองค์ประกอบตามแนวกลางของแต่ละแนวตั้ง)

ไอคอนตัวเลื่อน

ไอคอนที่เรียบง่ายรวมถึงโน้ตเสียงและสัญลักษณ์ "ระเบิด" ช่วยให้ผู้เล่นระบุถึงวัตถุประสงค์ของตัวเลื่อนเมื่อเปิดเมนูการตั้งค่า

ไอคอนบ่งบอกวัตถุประสงค์ของตัวเลื่อนในเมนูตั้งค่า.
  1. แทรก ImageLabel ลงในกรอบ EffectsVolumeSlider และเปลี่ยนชื่อเป็น Icon ไอคอนนี้จะช่วยให้ผู้เล่นเข้าใจว่าวัตถุประสงค์ในประสบการณ์ใดที่ตัวเลื่อนควบคุม.

    หน้าต่าง Explorer แสดงให้เห็นว่าแทรก ImageLabel ลงในกรอบ EffectsVolumeSlider.
  2. เมื่อเลือก Icon ให้ตั้งค่าดังนี้:

    • BackgroundTransparency = 1 (โปร่งใสเต็มที่)
    • Size = 2.5, 0, 2.5, 0 (250% สูงของกรอบหลักเมื่อจำกัดอัตราส่วน)
    • Image = rbxassetid://90019827067389 (ID ของทรัพย์สินโน้ตเสียงและสัญลักษณ์ "ระเบิด")
  3. แทรก UIAspectRatioConstraint ลงใน Icon และปล่อยให้คุณสมบัติเป็นค่าเริ่มต้น (1:1 ความกว้างต่อความสูง).

    หน้าต่าง Explorer แสดงให้เห็นว่ามีการแทรก UIAspectRatioConstraint ลงใน ImageLabel. ไอคอนที่เสร็จสิ้นในเมนูตั้งค่า.

กรอบช่วง

โดยตรงทางด้านขวาของ ไอคอน ส่วนที่โต้ตอบของตัวเลื่อนควรถูกเก็บภายใน Frame อื่น

ขนาดและตำแหน่งเป้าหมายของส่วนโต้ตอบของตัวเลื่อน.
  1. แทรก Frame ใหม่ลงในกรอบ EffectsVolumeSlider และเปลี่ยนชื่อเป็น SliderFrame โดยต้องเป็น ผู้พี่น้อง โดยตรงของ UIListLayout ตัวปรับเลย์เอาต์

    หน้าต่าง Explorer แสดงให้เห็นว่ามีการแทรก Frame ใหม่เข้าสู่กรอบ EffectsVolumeSlider.
  2. เมื่อเลือก SliderFrame ให้ตั้งค่าดังนี้:

  3. แทรกตัวปรับแต่งต่อไปนี้ลงใน SliderFrame:

    • UICorner โดยมีคุณสมบัติ CornerRadius ตั้งค่าเป็น 0.5, 0 (รูปทรง "พิล")
    • UISizeConstraint โดยมีคุณสมบัติ MaxSize ตั้งค่าเป็น inf, 30 (ความสูงสูงสุด 30 พิกเซล)
    • UIStroke โดยมีคุณสมบัติ Color ตั้งค่าเป็น 0, Thickness เป็น 3 และ Transparency เป็น 0.25 (โปร่งใส 75% สีดำ)
    กรอบเลื่อนถูกวางอยู่ทางด้านขวาของไอคอน.

ตัวจัดการโต้ตอบ

ด้วย ตัวเก็บตัวเลื่อน ที่สร้างขึ้นแล้ว คุณสามารถสร้าง ด้ามจับที่ลากได้ สำหรับผู้เล่นเพื่อทำการโต้ตอบในระหว่างการเล่นเกม

ด้ามจับเลื่อนที่โต้ตอบได้ตั้งอยู่ภายในกรอบช่วง.
  1. แทรก Frame ใหม่ลงในตัวเก็บ SliderFrame และเปลี่ยนชื่อเป็น Handle.

    หน้าต่าง Explorer แสดงให้เห็นว่ามีการแทรก Frame ลูกเข้ามาในกรอบ SliderFrame และเปลี่ยนชื่อเป็น Handle.
  2. เมื่อเลือก Handle ให้ตั้งค่าดังนี้:

    • AnchorPoint = 0.5 (จุดยึดกลาง)
    • Position = 0.5, 0, 0.5, 0 (ตรงกลางในแนวนอนและแนวตั้งของกรอบหลัก)
    • Size = 1.2, 0, 1.2, 0 (120% สูงของกรอบหลักเมื่อจำกัดอัตราส่วน)
    • ZIndex = 3 (การจัดเรียงด้ามจับให้เลเยอร์อยู่ข้างหน้าองค์ประกอบของตัวเลื่อนอื่น ๆ)
  3. แทรกโมดูลต่อไปนี้ลงใน Handle:

    • UIAspectRatioConstraint โดยมีคุณสมบัติเริ่มต้น (1:1 ความกว้างต่อความสูง)
    • UICorner โดยมีคุณสมบัติ CornerRadius ตั้งค่าเป็น 0.5, 0 (รูปทรงกลม)
    • UIStroke โดยมีคุณสมบัติ Color ตั้งค่าเป็น [0, 150, 255] และ Thickness เป็น 8 (ขอบสีฟ้าหนา)
  4. แทรกวัตถุ UIDragDetector ลงใน Handle วัตถุที่สะดวกนี้ช่วยให้เกิดการโต้ตอบและกระตุ้นการโต้ตอบกับองค์ประกอบ UI 2D

    หน้าต่าง Explorer แสดงให้เห็นว่ามีการแทรก UIDragDetector เข้าไปใน Frame Handle.
  5. ตั้งค่าคุณสมบัติเหล่านี้สำหรับ UIDragDetector ใหม่:

    • DragStyle = TranslateLine (การเคลื่อนไหว 1D ตาม DragAxis ของตัวตรวจจับ.)
    • ResponseStyle = Scale (เคลื่อนที่ด้วยค่าอัตราส่วนของตำแหน่งของผู้ตรวจจับที่อยู่ในพ่อของมัน)
  6. เพื่อให้แน่ใจว่าช่วงการลากเชิงเส้นของดรัมจับถูกจำกัดให้กับตัวเก็บของมัน ให้เชื่อมโยงคุณสมบัติ BoundingUI เข้ากับตัวเก็บ SliderFrame:

    1. เลือก UIDragDetector.
    2. คลิกที่คุณสมบัติ BoundingUI ในหน้าต่าง Properties.
    3. กลับไปที่หน้าต่าง Explorer คลิกที่ SliderFrame ซึ่งเป็นพ่อของดรัมจับ
    แผนภาพแสดงกระบวนการเชื่อมโยงคุณสมบัติ BoundingUI ของตัวตรวจจับไปยังตัวเก็บ SliderFrame.

    การเชื่อมโยงของ BoundingUI จะสะท้อนตัวเก็บ SliderFrame:

    หน้าต่าง Properties แสดงคุณสมบัติของตัวตรวจจับที่เชื่อมต่อกับตัวเก็บ SliderFrame.

หากคุณทดสอบการเล่นประสบการณ์ในขณะนี้ คุณจะสามารถลากด้ามจับไปทางซ้ายและขวาภายในตัวเก็บของมัน:

การเติมด้านใน

เพื่อบ่งบอกให้ชัดเจนยิ่งขึ้นว่าตัวเลื่อนควบคุมช่วง 0% ถึง 100% คุณสามารถเพิ่ม การเติมด้านใน ทางด้านซ้ายของตัวเก็บซึ่งจะซิงค์กับตำแหน่งที่แตกต่างของด้ามจับ

การเติมด้านในของตัวเลื่อนถูกแทรกลงใน SliderFrame.
  1. แทรก Frame ใหม่ลงในตัวเก็บ SliderFrame และเปลี่ยนชื่อเป็น InnerFill.

    หน้าต่าง Explorer แสดงให้เห็นว่ามีการแทรกกรอบลูกเข้าไปในกรอบ SliderFrame และเปลี่ยนชื่อเป็น InnerFill.
  2. ตั้งค่าคุณสมบัติสำหรับกรอบ InnerFill ดังนี้:

    • AnchorPoint = 0, 0.5 (ขอบซ้ายและแนวกลาง)
    • BackgroundColor3 = [0, 150, 255] (สีน้ำเงินที่เข้ากับด้ามจับของตัวเลื่อน)
    • BackgroundTransparency = 0.35 (โปร่งใส 65%)
    • Position = 0, 0, 0.5, 0
    • Size = 0.5, 0, 1, 0 (ความกว้าง 50% และความสูง 100% ของกรอบหลัก)
    • ZIndex = 2 (เลเยอร์อยู่ข้างหน้าเลเยอร์แม่ของตัวเก็บ/ขอบ)
  3. เพื่อให้ตรงกับรูปทรง "พิล" ของตัวเก็บหลัก SliderFrame ให้แทรกตัวปรับ UICorner และตั้งค่า CornerRadius เป็น 0.5, 0.

    หน้าต่าง Explorer แสดงให้เห็นว่ามีการแทรก UICorner ลงในกรอบ InnerFill.
    หน้าต่าง Properties แสดงค่าที่คาดหวังสำหรับ UICorner.
    กรอบ InnerFill ที่ตกแต่งด้วยพื้นหลังสีน้ำเงินและมุมโค้ง.

ทำซ้ำตัวเลื่อน

ด้วย ตัวเลื่อนแรก ที่สร้างขึ้นแล้ว คุณสามารถทำซ้ำได้ง่าย ๆ และเปลี่ยนแปลงบางด้านการมองเพื่อลดนัยยะใหม่ ในกรณีนี้คือตัวระดับเสียงของเสียงพื้นหลังที่มีสัญลักษณ์เป็นโน้ตเพลง

ตำแหน่งเป้าหมายของตัวเลื่อนเสียงพื้นหลัง.
  1. เลือก EffectsVolumeSlider ที่สมบูรณ์

    หน้าต่าง Explorer แสดงให้เห็นว่าเลือก EffectsVolumeSlider ที่สมบูรณ์.
  2. ทำการทำซ้ำ (CtrlD หรือ D) จากนั้นเปลี่ยนชื่อซ้ำเป็น BackgroundVolumeSlider.

    หน้าต่าง Explorer แสดงให้เห็นว่าตัวเลื่อนที่ทำโคลนถูกเปลี่ยนชื่อเป็น BackgroundVolumeSlider.
  3. เปลี่ยนตำแหน่งของตัวเลื่อนใหม่ให้เป็น Position เป็น 0.5, 0, 0.7, 0 เพื่อย้ายมันไปด้านล่างของตัวเลื่อนแรก.

    BackgroundVolumeSlider วางอยู่ด้านล่าง EffectsVolumeSlider.
  4. ขยายสาขาระดับบนสุดของ BackgroundVolumeSlider เลือก Icon label ภาพและเปลี่ยนคุณสมบัติ Image เป็น rbxassetid://101125859760167 (ID ของสัญลักษณ์โน้ตเพลง).

    หน้าต่าง Explorer แสดงให้เห็นว่าเป็นการเลือก Icon label ใน BackgroundVolumeSlider.
    หน้าต่าง Properties แสดงค่าที่คาดหวังสำหรับ Icon label.
    BackgroundVolumeSlider ที่มีการเปลี่ยนสัญลักษณ์ไอคอน.
  5. ขยายสาขา SliderFrame -> Handle เลือกโมดูล UIStroke ที่อยู่ภายในแล้วตั้งค่าคุณสมบัติ Color เป็น [255, 0, 125] (สีม่วง).

    หน้าต่าง Explorer แสดงให้เห็นว่า UIStroke อยู่ใน Handle ของ BackgroundVolumeSlider.
    หน้าต่าง Properties แสดงค่าที่คาดหวังสำหรับ UIStroke.
    BackgroundVolumeSlider ที่มีการเปลี่ยนภาพไอคอน.
  6. เลือกกรอบ InnerFill ภายใน SliderFrame และเปลี่ยนคุณสมบัติ BackgroundColor3 เป็นสีม่วงเดียวกัน ([255, 0, 125]).

    หน้าต่าง Explorer แสดงกรอบ InnerFill ภายใน SliderFrame ของ BackgroundVolumeSlider.
    หน้าต่าง Properties แสดงค่าที่คาดหวังสำหรับ InnerFill.
    BackgroundVolumeSlider ที่มีการเปลี่ยนสี InnerFill.

สร้างปุ่มปิด

องค์ประกอบสุดท้ายของเมนูตั้งค่าสคือ ปุ่มปิด ซึ่งให้ผู้เล่นมีการป้อนข้อมูลเพิ่มเติมในการปิดเมนู (ปุ่ม SettingsButton ที่อยู่กลางด้านบนจะทำหน้าที่เดียวกัน)

เมนูตั้งค่าพร้อมปุ่มปิดระบุไว้ในมุมบนขวา.
  1. แทรก ImageButton ใหม่ลงใน SettingsMenu และเปลี่ยนชื่อเป็น CloseButton.

    หน้าต่าง Explorer แสดงให้เห็นว่ามีการแทรก ImageButton ใหม่ลงใน SettingsMenu และเปลี่ยนชื่อเป็น CloseButton. ImageButton เปล่าในมุมบนซ้ายของเมนูตั้งค่า.
  2. เมื่อเลือก CloseButton แล้วให้ตั้งค่าดังนี้:

    • AnchorPoint = 1, 0 (มุมบนขวา)
    • BackgroundTransparency = 1 (โปร่งใสเต็มที่)
    • Position = 1, -10, 0, 10 (100 พิกเซลที่ยื่นออกจากมุมบนขวา)
    • Size = 0.15, 0, 0.15, 0 (15% ของความสูงของกรอบเมื่อจำกัดอัตราส่วน)
    • Image = rbxassetid://5577404210 (ID ของสัญลักษณ์ปิด)
    • ImageTransparency = 0.25 (โปร่งใส 75%)
  3. แทรก UIAspectRatioConstraint ลงในปุ่มด้วยค่าเริ่มต้น (1:1 ความกว้างต่อความสูง).

    หน้าต่าง Explorer แสดงให้เห็นว่ามีการแทรก UIAspectRatioConstraint ลงใน CloseButton. ปุ่มปิดที่เสร็จสมบูรณ์อยู่ในมุมบนขวาของเมนูตั้งค่า.

สร้างโมดูลควบคุม

โครงสร้าง โมดูลควบคุม ที่สามารถขยายได้ช่วยให้การจัดการ UI อินเทอร์แอคทีฟมีความลื่นไหลมากขึ้นกว่าเมื่อมีสคริปต์รายตัวที่วางอยู่ในแต่ละวัตถุ ModuleScripts จะทำให้ฟังก์ชันนี้ขยายได้ง่ายโดยให้คุณใช้โค้ดซ้ำระหว่างสคริปต์ในแต่ละด้านของพรมแดนหลัก/ลูกค้าหรือใกล้เคียง

ตัวควบคุมวัตถุที่มีสถานะ

โมดูลตัวควบคุมวัตถุที่มีสถานะนี้ช่วยให้คุณเพิ่มพฤติกรรมให้กับวัตถุ UI เช่น SettingsButton และ SettingsMenu และสลับ/ไล่ระดับระหว่างสถานะต่าง ๆ ได้อย่างง่ายดาย ในการสร้างโมดูล:

  1. แทรก ModuleScript ลงในตัวเก็บ ReplicatedStorage และเปลี่ยนชื่อเป็น StatefulObjectController.
หน้าต่าง Explorer แสดงโมดูล StatefulObjectController ภายในตัวเก็บ ReplicatedStorage.
  1. วางโค้ดต่อไปนี้ภายในโมดูล:

    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)
    -- Create tweens for reuse to avoid making new tweens every time state is changed
    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("Attempted to set %s to unknown state '%s'", self.object:GetFullName(), stateName))
    return
    end
    self.currentStateName = stateName
    -- Make sure other tweens aren't conflicting
    for _, tween in self.tweens do
    tween:Cancel()
    end
    stateTween:Play()
    end
    return StatefulObjectController
    สายวัตถุประสงค์
    610กำหนดและส่งออกประเภท Luau เพื่อปรับปรุงการทำงานอัตโนมัติและการตรวจสอบข้อผิดพลาดเมื่อใช้โมดูลนี้.
    1233ฟังก์ชันที่ใช้ในการเริ่มต้นและเพิ่มพฤติกรรมให้กับวัตถุ UI ที่มีสถานะ โดยรับ GuiObject เป็น object ตารางของสถานะและข้อมูลที่เกี่ยวข้อง TweenInfo และชื่อสถานะแรก ภายในฟังก์ชันนี้ สาย 2628 สร้าง Tweens สำหรับแต่ละสถานะ และสาย 30 จะเรียกฟังก์ชัน setState() ของโมดูลเพื่อตั้งค่าวัตถุให้เป็นสถานะแรก.
    3550ฟังก์ชันที่ใช้ในการตั้งค่า/เปลี่ยนสถานะของวัตถุที่มีสถานะ ภายในฟังก์ชันนี้ สาย 42 ตั้งค่า currentStateName ของวัตถุให้เป็นสถานะที่จะตั้งค่า สาย 4547 ยกเลิก tweens ที่กำลังดำเนินการอยู่เพื่อป้องกันความขัดแย้ง และสาย 49 ทำให้ tween(s) ของสถานะทำงาน.

ตัวควบคุมตัวเลื่อน

โมดูลเพิ่มเติมในการเริ่มต้นและควบคุมตัวเลื่อนเสียงสองตัวนี้ ยังอนุญาตให้คุณเชื่อมต่อฟังก์ชันคืนค่ากับแต่ละตัวเลื่อนเพื่อตรวจจับการเข้าใช้งานของผู้เล่นกับตัวเลื่อนและปรับเปลี่ยนตามที่ต้องการในประสบการณ์

  1. แทรก ModuleScript ลงในตัวเก็บ ReplicatedStorage และเปลี่ยนชื่อเป็น SliderController.

    หน้าต่าง Explorer แสดงว่า SliderController โมดูลอยู่ภายในตัวเก็บ ReplicatedStorage.
  2. วางโค้ดต่อไปนี้ภายในโมดูล:

    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("Attempted to hydrate slider %s but couldn't find Handle", object:GetFullName()))
    end
    local innerFill = object:FindFirstChild("InnerFill", true)
    if not innerFill then
    warn(string.format("Attempted to hydrate slider %s but couldn't find InnerFill", object:GetFullName()))
    end
    local dragDetector = handle:FindFirstChildWhichIsA("UIDragDetector")
    if not dragDetector then
    warn(string.format("Attempted to hydrate slider %s but couldn't find UIDragDetector", object:GetFullName()))
    end
    local self = setmetatable({
    handle = handle,
    innerFill = innerFill,
    dragDetector = dragDetector,
    value = initialValue or 0.5,
    onChanged = onChanged,
    }, SliderController)
    -- Set initial value
    self:setValue(self.value)
    -- Connect detector to player manipulation
    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
    -- Update the handle position and inner frame size to match
    self.handle.Position = UDim2.fromScale(clampedValue, 0.5)
    self.innerFill.Size = UDim2.fromScale(clampedValue, 1)
    -- Run the user's callback with the latest value
    local changeSuccess, changeResult = pcall(self.onChanged, clampedValue)
    if not changeSuccess then
    warn("Error in slider callback:", changeResult)
    end
    end
    return SliderController
    สายวัตถุประสงค์
    746ฟังก์ชันการเริ่มต้นและเพิ่มพฤติกรรมให้กับองค์ประกอบตัวเลื่อน โดยรับ Frame ของตัวเลื่อนเป็น object ฟังก์ชันย้อนกลับ onChanged เพื่อดำเนินการเมื่อมีการเปลี่ยนแปลงตัวเลื่อน และค่าที่เริ่มต้นสำหรับตำแหน่งด้ามจับของตัวเลื่อน ภายในฟังก์ชัน สาย 1427 จะยืนยันว่ามีการควบคุม Handle, Inner fill, และ UIDragDetector มีอยู่ สาย 38 จะเรียกฟังก์ชัน setValue() ของโมดูลและสาย 4143 จะเชื่อมต่อเหตุการณ์ DragContinue ของตัวตรวจจับเข้ากับฟังก์ชัน setValue() ของโมดูล (ดูข้อมูลเพิ่มเติมได้ด้านล่าง).
    4861ฟังก์ชันที่ใช้ในการตั้งค่า/เปลี่ยนค่าให้กับตัวเลื่อน ภายในฟังก์ชัน สาย 5354 จะทำให้ตำแหน่งของด้ามจับและขนาดของกรอบด้านในซิงโครไนซ์ และสาย 57 จะส่งค่าที่เปลี่ยนให้กับฟังก์ชันย้อนกลับเพื่อให้คุณสามารถใช้ค่าดังกล่าวได้ตามต้องการ.

สร้างสคริปต์การตั้งค่า

ด้วย ปุ่มตั้งค่า และ เมนูตั้งค่า ที่เสร็จสมบูรณ์แล้ว คุณสามารถเชื่อมโยงทุกอย่างเข้าด้วยกันด้วยสคริปต์เดียวที่ใช้ โมดูลควบคุม.

  1. แทรก LocalScript ใหม่ลงใน HUDContainer และเปลี่ยนชื่อเป็น SettingsScript เพื่อบรรยายถึงวัตถุประสงค์ของมัน โปรดทราบว่าสคริปต์นี้ควรอยู่ในระดับเดียวกัน (ผู้พี่น้อง) กับ SettingsMenu และ SettingsButton ซึ่งเป็นวัตถุ UI ระดับบนที่มันจะจัดการ.

    หน้าต่าง Explorer แสดงให้เห็นว่ามีสคริปต์ SettingsScript อยู่ในตัวเก็บ HUDContainer.
  2. วางโค้ดต่อไปนี้ภายในสคริปต์:

    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
    -- Initialize settings button
    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"
    })
    -- Initialize settings menu frame
    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"
    })
    -- Initialize effects volume slider
    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,
    })
    -- Initialize background volume slider
    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,
    })
    -- Connect buttons to player interaction
    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. อ้างอิงจากส่วนเหล่านี้เพื่อสำรวจว่าสคริปต์ใช้โมดูลควบคุมอย่างไร:

    สาย 10-27 เริ่มต้นและเพิ่มพฤติกรรมให้กับ ปุ่มตั้งค่า ดังนี้:

    สายวัตถุประสงค์
    1011อ้างอิงในท้องถิ่น settingsButton ถูกประกาศและเติมน้ำด้วยฟังก์ชัน StatefulObjectController.hydrate() และปุ่ม SettingsButton ภายใน HUDContainer ถูกอ้างถึงเป็นวัตถุในการเติมน้ำ.
    1225มีการส่งผ่านตาราง states ที่มีสองสถานะที่ไม่ซ้ำกัน คือ menuOpen และ menuClosed สถานะแต่ละสถานะมีการเปลี่ยนแปลงที่แจ้งให้ทราบ (ผ่าน TweenInfo) ว่าสถานะเฉพาะจะไปถึงคุณสมบัติเป้าหมายอย่างไรที่กำหนดไว้ในตาราง properties ในกรณีนี้ menuOpen กำหนดการเปลี่ยนแปลงสถานะที่ 45° สำหรับ Rotation ของปุ่มพร้อมกับ Exponential tween เป็นเวลา ½ วินาที ในขณะที่ menuClosed จะคืนปุ่มไปยังการหมุนปกติที่ 0.
    26สถานะ เริ่มต้น ของปุ่มถูกตั้งค่าเป็น menuClosed (สามารถตั้งค่าได้ในชื่อสถานะใดๆ ที่อยู่ภายในตาราง states).

    ต่อไปในสคริปต์ (สาย 76-86) ปุ่มถูกเชื่อมต่อกับการโต้ตอบของผู้เล่นเพื่อกระตุ้นการเปลี่ยนแปลงสถานะ UI:

    สายวัตถุประสงค์
    7682SettingsButton เชื่อมต่อกับเหตุการณ์ Activated ของ ชนิด GuiButton เพื่อเรียกฟังก์ชันที่ไม่ระบุชื่อ ภายในฟังก์ชันที่ไม่ระบุชื่อนี้ เส้น 7779 สลับค่าตัวแปร targetState ระหว่าง menuOpen และ menuClosed ต่อไปที่สาย 80 เรียกใช้ setState() เพื่อกำหนดสถานะให้กับปุ่มเป็น targetState และสาย 81 ก็ทำเช่นเดียวกันกับ SettingsMenu เพื่อให้เปิดหรือปิดด้วยการเปิดใช้งาน SettingsButton.
    8386CloseButton เชื่อมต่อกับเหตุการณ์ Activated เพื่อเรียกฟังก์ชันที่ไม่ระบุชื่อซึ่งตั้งค่าสถานะของทั้ง SettingsButton และ SettingsMenu เป็น menuClosed.

    สาย 30-49 เริ่มต้นและเพิ่มพฤติกรรมให้กับ เมนูตั้งค่า ดังนี้:

    บรรทัดวัตถุประสงค์
    3031มีการประกาศอ้างอิงท้องถิ่น settingsMenu และมีการเติมข้อมูลด้วยฟังก์ชัน StatefulObjectController.hydrate() และมีการอ้างอิงเฟรม SettingsMenu ภายใน HUDContainer เป็นวัตถุที่ต้องการเติมข้อมูล
    3246คล้ายกับปุ่มตั้งค่า มีการส่งตาราง states ที่มีสถานะเฉพาะสองสถานะ คือ menuOpen และ menuClosed ที่นี่ menuOpen จะประกาศการเปลี่ยนแปลงสถานะเป็น UDim2.fromScale(0.5, 0.5) สำหรับ Position ของเฟรมพร้อมกับการ Tween สไตล์การเคลื่อนไหว Bounce เป็นระยะเวลา ½ วินาที ซึ่งยังมีสถานะ Visible เป็น true ในทางตรงกันข้าม menuClosed จะประกาศการเปลี่ยนแปลงสถานะตำแหน่งเป็น UDim2.fromScale(0.5, 0.4) และ Visible เป็น false แต่ TweenInfo ที่มีระยะเวลา 0 ในบรรทัด 41 จะทำให้การเปลี่ยนแปลงสถานะเกิดขึ้นทันที
    48สถานะเริ่มต้นของเฟรมถูกตั้งค่าเป็น menuClosed

    ในสคริปต์ (บรรทัด 76-86) เมนูการตั้งค่าจะเชื่อมโยงกับการโต้ตอบของผู้เล่น:

    บรรทัดวัตถุประสงค์
    81ตั้งค่า targetState เดียวกันสำหรับ SettingsMenu ให้อัพเดตเมื่อมีการเปิดใช้งาน SettingsButton
    85ตั้งสถานะของ SettingsMenu เป็น menuClosed เมื่อมีการเปิดใช้งาน CloseButton

    บรรทัด 51-73 สร้างและแนบพฤติกรรมกับ EffectsVolumeSlider และ BackgroundVolumeSlider ดังนี้:

    บรรทัดวัตถุประสงค์
    52ตั้งค่าอ้างอิงท้องถิ่นไปยัง Effects SoundGroup ภายใน SoundService ซึ่ง SoundGroup ช่วยให้คุณเชื่อมโยงเสียงหลายๆ เสียง (Sounds) และควบคุมระดับเสียงของเสียงแต่ละเสียงในกลุ่มผ่านคุณสมบัติ Volume ของกลุ่ม
    5354มีการประกาศอ้างอิงท้องถิ่น effectsVolumeSlider และมีการเติมข้อมูลด้วยฟังก์ชัน SliderController.hydrate() โดยมีเฟรม EffectsVolumeSlider ภายใน HUDContainer ⟩ SettingsMenu เป็นวัตถุที่ต้องการเติมข้อมูล โปรดทราบว่าพารามิเตอร์ที่สองของ true สำหรับ FindFirstChild() จะแจ้งให้เมธอดมองหาแบบย้อนกลับในสาขา HUDContainer เพื่อตรวจหา EffectsVolumeSlider
    55ค่าตั้งต้นของตัวเลื่อนถูกตั้งค่าเป็น Volume ปัจจุบันของกลุ่มเสียง Effects หรือ 0.5 เป็นค่าเริ่มต้น
    5660สร้างฟังก์ชัน callback เพื่อนำการเปลี่ยนแปลงค่าตัวเลื่อนไปใช้กับระดับเสียงของกลุ่มเสียง Effects
    6473โดยพื้นฐานแล้วเหมือนกับบรรทัด 52-61 ยกเว้นการเติมข้อมูลเฟรม BackgroundVolumeSlider ภายใน HUDContainer ⟩ SettingsMenu และนำการเปลี่ยนแปลงค่าตัวเลื่อนไปใช้กับระดับเสียงของกลุ่มเสียง Background

ด้วย SettingsScript ที่อยู่ในสถานที่ ประสบการณ์ตอนนี้มี UI แบบโต้ตอบที่ทำงานได้อย่างสมบูรณ์ ซึ่งเชื่อมโยงชุดของวัตถุ UI ที่เกี่ยวข้องกับการโต้ตอบของผู้เล่น

©2026 Roblox Corporation. Roblox, โลโก้ Roblox และ Powering Imagination เป็นส่วนหนึ่งของเครื่องหมายการค้าที่จดทะเบียน และไม่ได้จดทะเบียนของเราในสหรัฐฯ และประเทศอื่นๆ