เสียง 3D คือเสียงที่มาจากตำแหน่งเฉพาะในพื้นที่ 3D ซึ่งมีการปรับเพิ่มหรือลดเสียงตามระยะทางและทิศทางระหว่างแหล่งปล่อยเสียงและผู้ฟัง นี่หมายความว่าเมื่อผู้ฟังหรือผู้ปล่อยเสียงเคลื่อนที่ไปรอบ ๆ สภาพแวดล้อม ผู้เล่นสามารถได้ยินเสียงเหล่านั้นจากทิศทางและระดับเสียงที่แตกต่างกันได้แบบไดนามิก
โดยใช้ไฟล์ Gingerbread House - Start .rbxl เป็นจุดเริ่มต้นและ Gingerbread House - Complete Audio เป็นข้อมูลอ้างอิง บทเรียนนี้จะแสดงให้คุณเห็นวิธีการเพิ่มเสียง 3D ทั้งแบบวนซ้ำและแบบช็อตเดียวในประสบการณ์ของคุณ รวมถึงคำแนะนำในการ:
- เสียงเชิงสิ่งแวดล้อมที่เล่นเมื่อผู้เล่นเชื่อมต่อกับเซิร์ฟเวอร์แล้ว
- การเรียกเสียงเพื่อแจ้งผู้เล่นเกี่ยวกับเหตุการณ์สำคัญในสถานการณ์ที่สำคัญต่อการเล่นเกมของพวกเขา
- การเปิดเสียงเพื่อให้ผู้เล่นได้รับฟีดแบ็กด้วยเสียงเมื่อพวกเขามีปฏิสัมพันธ์กับวัตถุ 3D
- การเล่นเสียงคำพูดของตัวละครที่ดึงดูดและแนะนำผู้เล่นไปยังจุดที่น่าสนใจภายในพื้นที่ของพวกเขา
หากคุณติดขัดในกระบวนการนี้ คุณสามารถใช้ Gingerbread House - Complete Audio เป็นข้อมูลอ้างอิงเพื่อเปรียบเทียบความก้าวหน้าของคุณได้
วัตถุเสียง
ในการสร้างเสียงเชิงทิศทาง จำเป็นต้องเข้าใจว่าวัตถุเสียงที่จะใช้ในบทเรียนนี้มี 6 ประเภทหลักในการสร้างเสียง 3D:
- วัตถุ AudioPlayer โหลดและเล่น ไฟล์เสียง
- วัตถุ AudioEmitter คือ ลำโพงเสมือน ที่ปล่อยเสียงในสภาพแวดล้อม 3D
- วัตถุ AudioListener คือ ไมโครโฟนเสมือน ที่รับเสียงจากสภาพแวดล้อม 3D
- วัตถุ AudioDeviceOutput คือ อุปกรณ์ฮาร์ดแวร์จริง ในโลกจริง เช่น ลำโพงหรือหูฟัง
- วัตถุ AudioDeviceInput คือ ไมโครโฟนจริง ในโลก
- Wires ส่งเสียงจากวัตถุหนึ่งไปยังอีกวัตถุหนึ่ง
วัตถุเสียงทั้งหมดนี้ทำงานร่วมกันเพื่อปล่อยเสียงเช่นเดียวกับอุปกรณ์จริงในโลก มาเพิ่มเติมดูว่าในทางปฏิบัติมันทำงานอย่างไร โดยใช้ตัวอย่างของผู้เล่นที่สวมหูฟังขณะเล่นประสบการณ์ด้วยแล็ปท็อปของพวกเขา:
- วัตถุ AudioPlayer โหลด 1516791621 ID ของอุปกรณ์เสียงเข้าสู่ประสบการณ์สำหรับเพลงฝน
- วัตถุ AudioEmitter ปล่อยเสียงของเพลงฝนเข้าสู่สภาพแวดล้อม 3D
- วัตถุลูกของตัวละคร AudioListener ฟังเสียงภายในสภาพแวดล้อม 3D แล้วส่งกลับให้หูฟังของพวกเขา
- วัตถุ AudioDeviceOutput ส่งเสียงจาก AudioListener ไปยังลำโพงจริงของผู้เล่น หรือในกรณีนี้คือหูฟังของพวกเขา
- วัตถุ AudioDeviceInput บันทึกเสียงจากโลกจริงและส่งกลับเข้าไปในประสบการณ์สำหรับการสนทนาเสียง


ส่วนถัดไปจะมีการเจาะลึกและอ้างอิงถึงวัตถุเหล่านี้ในขณะที่คุณเรียนรู้วิธีการเล่นเสียง 3D ทั้งแบบวนซ้ำและแบบช็อตเดียว ขณะที่คุณตรวจสอบวัตถุเหล่านี้ด้วยเทคนิคที่จะตามมา คุณจะสามารถคาดการณ์ได้อย่างแม่นยำว่าวิธีการบันทึกเสียงและส่งเสียงจากประสบการณ์ไปยังผู้เล่นและในทางกลับกันเป็นอย่างไร
เสียงวนซ้ำ
เสียง 3D แบบวนซ้ำ หรือเสียงเชิงทิศทางที่เล่นซ้ำอย่างราบรื่นเมื่อผู้เล่นเชื่อมต่อกับเซิร์ฟเวอร์ เป็นเทคนิคการออกแบบเสียงทั่วไปที่ช่วยเพิ่มบรรยากาศของพื้นที่ 3D โดยทำให้รู้สึกมีชีวิตชีวาและไดนามิก นอกจากนี้ เสียง 3D แบบวนซ้ำยังทำให้แหล่งเสียงในสภาพแวดล้อมของคุณเป็นไปอย่างสม่ำเสมอ เช่น เสียงของทีวีที่มีเสียงหึ่ง ๆ หรือเสียงน้ำตก หากเสียงเหล่านี้หยุดลงโดยทันที สภาพแวดล้อมจะรู้สึกไม่สมจริง
เพื่อแสดงให้เห็นถึงแนวคิดนี้ ให้ดูว่าเสียง 3D สำหรับน้ำตกขนาดใหญ่สองแห่งนี้หยุดเมื่อเสียงที่ไม่ได้วนซ้ำสิ้นสุด เมื่อเสียงน้ำเริ่มต้นทำให้ผู้เล่นดำดิ่งสู่สภาพแวดล้อมกลางแจ้ง การเปลี่ยนแปลงในเสียงอย่างกะทันหันนั้นทำให้รู้สึกสะดุดและไม่เป็นธรรมชาติเมื่อเทียบกับการที่น้ำตกทำงานในโลกจริง
ในทำนองเดียวกัน เน 샘พลใช้เทคนิคนี้สำหรับน้ำตกช็อกโกแลตที่ไหล และปรับระดับเสียงตามระยะห่างของผู้เล่นจากผู้ปล่อยเสียง เมื่อผู้เล่นอยู่ห่างน้อยกว่า 20 สตูด ก็จะปล่อยเสียงที่ระดับเสียงเต็ม เมื่อผู้เล่นเคลื่อนที่ออกไปอีก เสียงน้ำกระฉอกจะลดระดับเสียงลงทุกๆ 20 สตูดจากผู้ปล่อยเสียง นี่จำลองเสียงในโลกที่ลดลงไปตามระยะที่คุณอยู่จากแหล่งเสียง
ในการสร้างเสียง 3D แบบวนซ้ำในไฟล์ตัวอย่าง Gingerbread House - Complete Audio:
เปิดใช้งานผู้ฟังเริ่มต้นที่เชื่อมโยงกับตัวละครผู้เล่นของคุณ
- ในหน้าต่าง Explorer ให้เลือก SoundService
- ในหน้าต่าง Properties ให้ตั้งค่า DefaultListenerLocation เป็น Character เมื่อคุณเรียกประสบการณ์ เครื่องยนต์จะทำการสร้าง:
- วัตถุ AudioListener ภายใต้ Humanoid.RootPart ของตัวละครแต่ละตัว เพื่อให้คุณสามารถได้ยินเสียงที่เปลี่ยนไปในลำโพงของคุณตามตำแหน่งและขนาดของแหล่งเสียงในประสบการณ์
- วัตถุ AudioDeviceOutput ภายใต้ SoundService
ในหน้าต่าง Explorer ให้ไปที่ Workspace ⟩ WaterfallAudioObject, จากนั้น:
- แทรกวัตถุ AudioPlayer เพื่อสร้างแหล่งเสียงสำหรับน้ำตก
- แทรกวัตถุ AudioEmitter เพื่อปล่อยเสียงเชิงตำแหน่งจาก WaterfallAudioObject
- แทรกวัตถุ Wire เพื่อพาเสียงจาก AudioPlayer ไปยัง AudioEmitter

เลือก AudioPlayer แล้วในหน้าต่าง Properties,
- ตั้งค่า AssetID เป็น rbxassetid://1516791621 เพื่อเล่นเสียงฝน
- เปิดใช้งาน Looping เพื่อให้เสียงเล่นซ้ำอย่างราบรื่น
เลือก AudioEmitter แล้วในหน้าต่าง Properties ตั้งค่า DistanceAttenuation เป็น {0: 1}, {20: 0.8}, {40: 0.4}, {80: 0} เพื่อให้เสียงค่อย ๆ ลดลงตามระดับเสียงทุก ๆ 20 สตูดจากผู้ปล่อยเสียง
เลือก Wire แล้วในหน้าต่าง Properties,
- ตั้งค่า SourceInstance เป็น AudioPlayer ใหม่ของคุณเพื่อระบุว่าคุณต้องการให้สายไฟนำเสียงจากผู้เล่นเสียงนี้
- ตั้งค่า TargetInstance เป็น AudioEmitter ใหม่ของคุณเพื่อระบุว่าคุณต้องการให้สายไฟนำเสียงไปยังผู้ปล่อยเสียงที่เฉพาะเจาะจงในน้ำตกนี้
กลับไปที่หน้าต่าง Explorer แทรก Script ลงใน WaterfallAudioObject, เปลี่ยนชื่อเป็น LoopWaterfallMusic, ตั้งค่า RunContext ของมันเป็น Client, แล้ววางโค้ดต่อไปนี้ลงในสคริปต์:
local audioPlayer = script.ParentaudioPlayer:Play()คำอธิบายโค้ดสคริปต์เริ่มต้นโดยการประกาศตัวแปรเพื่อเป็นตัวแทนของผู้เล่นเสียง AudioPlayer สคริปต์จะตั้งค่าให้แหล่งเสียงเล่นตั้งแต่ผู้เล่นเข้าร่วมประสบการณ์ไปจนถึงเมื่อพวกเขาออกจากประสบการณ์
ทดสอบเล่นประสบการณ์เพื่อฟังเสียงฝนช็อกโกแลตเมื่ออวตาร์ของคุณอยู่ใกล้น้ำตก เมื่อคุณหมุนหัวของตัวละครไปในทิศทางที่แตกต่าง เสียงจะปรับไปยังลำโพงของคุณตามตำแหน่งของผู้ปล่อยเสียงในพื้นที่ 3D
เสียงช็อตเดียว
เสียง 3D แบบช็อตเดียว, หรือเสียงเชิงทิศทางที่เล่นเพียงครั้งเดียวในช่วงเวลาหรือถานะเฉพาะนอกจากจะมีการกระตุ้นโดยผู้เล่นอีกครั้ง จะช่วยให้ผู้เล่นเข้าใจเกี่ยวกับการกระทำของพวกเขา สภาพแวดล้อม และอักขระอื่น ๆ ที่อยู่รอบตัว พิจารณาใช้ฟีดแบ็คเสียงเช่นนี้ในประสบการณ์ของคุณเป็นสิ่งสำคัญ เพราะมันช่วยให้ผู้เล่นสามารถตัดสินใจเชิงกลยุทธ์ เช่น การหลีกเลี่ยงศัตรูที่กำลังจะเข้ามาหรือการหยิบของที่มีประโยชน์
ส่วนถัดไปมีรายละเอียดการนำไปใช้สำหรับสถานการณ์การเล่นเกมทั่วไปที่ผู้เล่นต้องการฟีดแบ็คเสียงเชิงทิศทางในเวลาที่เหมาะสม รวมถึงเหตุการณ์สถานการณ์การเล่นเกม การโต้ตอบกับวัตถุและบทสนทนาของตัวละครที่ไม่สามารถเล่นได้
ฟีดแบ็คเหตุการณ์
เมื่อผู้เล่นกระตุ้นเหตุการณ์สำคัญในสถานการณ์ภายในสภาพแวดล้อม เช่น การปลดล็อกพื้นที่การเล่นใหม่ หรือกระตุ้นการยิงของศัตรู สิ่งสำคัญคือต้องให้พวกเขาเข้าใจว่าในพื้นที่ 3D พวกเขาควรจดจ่อความสนใจที่ไหน หากพวกเขาไม่ได้รับฟีดแบ็คเสียงอย่างทันที พวกเขาอาจพลาดข้อมูลที่สำคัญต่อการเล่นเกมของพวกเขา ทำให้เกิดความไม่พอใจจากการไม่รู้ว่าจะไปทางไหนหรือจะทำอะไรต่อไป
เพื่อแสดงให้เห็นว่าทำไมจึงสำคัญ มาดูเสียง 3D แบบช็อตเดียวจากต้นแบบ Laser Tag ที่เล่นจากปืนลมของผู้เล่นแต่ละคน:
- มีเสียงป๊อปที่ลึกสำหรับการยิงทุกครั้งที่ผู้เล่นยิงจากปืนของเขา
- จะมีเสียงคลิกและเสียงบีบี๊อร์ที่เล่นทุกครั้งที่ผู้เล่นทำการรีโหลดปืน
เสียงเหล่านี้ช่วยให้ความตระหนักถึงสถานการณ์โดยการเตือนผู้เล่นที่อยู่ใกล้เคียงว่าทิศทางของการยิงมาจากไหน เพื่อให้พวกเขาตัดสินใจได้อย่างมีข้อมูลว่าจะเข้าร่วมสนุกหรือหลีกเลี่ยงอันตราย
ตัวอย่างนี้ใช้เทคนิคเดียวกันเพื่อจัดเตรียมความตระหนักถึงสถานการณ์สำหรับรางวัลของผู้เล่นสำหรับการทำภารกิจหลักให้สำเร็จ หลังจากที่พวกเขารวบรวมลูกอมสามลูก ประตูของบ้านขนมปังขิงจะเปิดเพื่อให้ผู้เล่นเข้าถึงของขวัญข้างใน
เนื่องจากไม่มีลำดับเฉพาะที่ผู้เล่นต้องเก็บรวบรวมลูกอมจึงเป็นสิ่งสำคัญที่ผู้เล่นจะต้องรับรู้ถึงการเปิดประตูไม่ว่าเมื่อใดก็ตามที่พวกเขารวบรวมลูกอมใด ๆ เสียงเชิงตำแหน่งทำให้สิ่งนี้เป็นไปได้เพื่อให้ผู้เล่นรับรู้ถึงความสำเร็จของพวกเขาและที่พวกเขาต้องไปต่อไปไม่ว่าสิ่งนี้จะอยู่ห่างออกไปจากประตูอย่างไร
ในการสร้างฟีดแบ็คเสียง 3D แบบช็อตเดียวในไฟล์ตัวอย่าง Gingerbread House - Complete Audio:
ในหน้าต่าง Explorer ให้ไปที่ Workspace ⟩ Door, จากนั้น:
- แทรกวัตถุ AudioPlayer เพื่อสร้างแหล่งเสียงสำหรับกลุ่มทั่ว
- แทรกวัตถุ AudioEmitter เพื่อปล่อยเสียงเชิงตำแหน่งจาก Door
- แทรกวัตถุ Wire เพื่อพาเสียงจาก AudioPlayer ไปยัง AudioEmitter

เลือก AudioPlayer แล้วในหน้าต่าง Properties ตั้งค่า AssetID เป็น rbxassetid://5930776613 เพื่อเล่นเสียงของประตูที่เหล็กเลื่อน
เลือก Wire แล้วในหน้าต่าง Properties,
- ตั้งค่า SourceInstance เป็น AudioPlayer ใหม่ของคุณเพื่อระบุว่าคุณต้องการให้สายไฟนำเสียงจากผู้เล่นเสียงนี้
- ตั้งค่า TargetInstance เป็น AudioEmitter ใหม่ของคุณเพื่อระบุว่าคุณต้องการให้สายไฟนำเสียงไปยังผู้ปล่อยเสียงที่เฉพาะเจาะจงภายในกลุ่มทั่ว
กลับไปที่หน้าต่าง Explorer ให้ไปที่ ServerScriptService, จากนั้นแทรก Script, เปลี่ยนชื่อเป็น GumdropService, ตั้งค่า RunContext ของมันเป็น Server, แล้ววางโค้ดต่อไปนี้ลงในสคริปต์:
-- การประกาศตัวแปรlocal Workspace = game:GetService("Workspace")local Players = game:GetService("Players")local ServerStorage = game:GetService("ServerStorage")local TweenService = game:GetService("TweenService")-- โมดูลlocal Leaderboard = require(ServerStorage.Leaderboard)local PlayerData = require(ServerStorage.PlayerData)-- ตัวแปรlocal gumdropsFolder = Workspace.Gumdropslocal gumdrops = gumdropsFolder:GetChildren()local GUMDROP_KEY_NAME = PlayerData.GUMDROP_KEY_NAMElocal GUMDROP_AMOUNT_TO_ADD = 1local function updatePlayerGumdrops(player, updateFunction)-- อัปเดตตารางลูกอมlocal newGumdropAmount = PlayerData.updateValue(player, GUMDROP_KEY_NAME, updateFunction)-- อัปเดตกระดานคะแนนลูกอมLeaderboard.setStat(player, GUMDROP_KEY_NAME, newGumdropAmount)-- ตรวจสอบว่าผู้เล่นได้เก็บรวบรวมลูกอมสามลูกif newGumdropAmount >= 3 then-- เล่นเสียงของเหตุการณ์ประตูเมื่อผู้เล่นเก็บรวบรวมลูกอมสามลูกlocal audioPlayer = Workspace.Door.AudioPlayeraudioPlayer:Play()-- ค่อยๆเลื่อนประตูลงมาlocal doorPart = Workspace.Doorlocal tweenInfo = TweenInfo.new(2, Enum.EasingStyle.Linear)local tween = TweenService:Create(doorPart, tweenInfo, {Position = doorPart.Position + Vector3.new(0, -15, 0)})tween:Play()endend-- กำหนดฟังก์ชันตัวจัดการเหตุการณ์local function onGumdropTouched(otherPart, gumdrop)if gumdrop:GetAttribute("Enabled") thenlocal character = otherPart.Parentlocal player = Players:GetPlayerFromCharacter(character)if player then-- ผู้เล่นแตะลูกอมlocal audioPlayer = gumdrop.AudioPlayeraudioPlayer:Play()gumdrop.Transparency = 1gumdrop:SetAttribute("Enabled", false)updatePlayerGumdrops(player, function(oldGumdropAmount)oldGumdropAmount = oldGumdropAmount or 0return oldGumdropAmount + GUMDROP_AMOUNT_TO_ADDend)print("ผู้เล่นเก็บรวบรวมลูกอม")endendend-- ตั้งค่า event listenersfor _, gumdrop in gumdrops dogumdrop:SetAttribute("Enabled", true)gumdrop.Touched:Connect(function(otherPart)onGumdropTouched(otherPart, gumdrop)end)endคำอธิบายโค้ดสคริปต์เริ่มต้นโดยการประกาศ Workspace, Players, ServerStorage, และ TweenService เพื่อให้สามารถอ้างอิงลูกและฟังก์ชัน ของพวกเขา จากนั้นจึงต้องการโมดูล Leaderboard และ PlayerData ใน ServerStorage; โมดูลเหล่านี้มีหน้าที่สร้างและอัปเดตกระดานคะแนนในมุมขวาบนของหน้าจอที่ติดตามจำนวนลูกอมที่ผู้เล่นรวบรวมในสภาพแวดล้อม
ฟังก์ชัน updatePlayerGumdrops ของสคริปต์เป็นที่ที่เกิดการทำงานมากที่สุดในกระบวนการกระตุ้นเสียง 3D สำหรับฟีดแบ็คเหตุการณ์ และมีพารามิเตอร์สองตัว:
- player - ผู้เล่นที่เก็บรวบรวมลูกอม
- updateFunction - ฟังก์ชันความช่วยเหลือที่อัปเดตจำนวนลูกอมที่เก็บรวบรวมของผู้เล่น
เมื่อตัวละครผู้เล่นชนเข้ากับลูกอม สคริปต์จะ:
- รับค่าจำนวนลูกอมใหม่ของผู้เล่นโดยเรียกใช้งานฟังก์ชัน PlayerData.updateValue
- อัปเดตกระดานคะแนนโดยค่าจำนวนใหม่นี้โดยเรียกใช้งานฟังก์ชัน Leaderboard.setStat
- ตรวจสอบว่าจำนวนนี้มีค่ามากกว่าหรือเท่ากับ 3
เมื่อตัวเลขนี้มากกว่าหรือเท่ากับ 3, สคริปต์จะ
- เล่นเสียง 3D จากผู้เล่นเสียงไปยังผู้ปล่อยเสียง
- ค่อย ๆ เคลื่อนที่ประตูเลื่อนไปยังตำแหน่งที่ต่ำกว่าอีกราว 15 สตูด
ส่วนที่เหลือของรหัสของสคริปต์จะเป็นผู้รับผิดชอบในการตรวจจับทุกอย่างที่ชนกับลูกอมว่าเป็นผู้เล่นเพื่อที่จะได้กระตุ้นเสียงที่ไม่เชิงตำแหน่งสำหรับฟีดแบ็คการเก็บรวบรวม สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับส่วนนี้ของสคริปต์ ให้ดูที่ Add 2D audio - Gameplay feedback.
ทดสอบเล่นประสบการณ์เพื่อฟังเสียงประตูที่เหล็กเลื่อนหลังจากที่คุณเก็บรวบรวมลูกอมสามลูกในสภาพแวดล้อม เมื่อคุณหมุนกล้อง เสียงจะปรับไปยังลำโพงของคุณตามตำแหน่งของผู้ปล่อยเสียงในพื้นที่ 3D
การโต้ตอบกับวัตถุ
เมื่อผู้เล่นโต้ตอบกับวัตถุ 3D ในสภาพแวดล้อม เช่น เปิดสวิตช์ไฟล์หรือหยิบอาวุธ เป็นสิ่งสำคัญที่ต้องให้ฟีดแบ็กที่ทันทีเพื่อให้พวกเขาเข้าใจได้อย่างชัดเจนว่า อย่างไร พวกเขากำลังโต้ตอบกับวัตถุ การจับคู่ระหว่างฟีดแบ็กภาพและฟีดแบ็กเสียงช่วยสร้างความสัมพันธ์ระหว่างสาเหตุและผลลัพธ์ระหว่างการกระทำของผู้เล่นกับระดับเสียงที่ตอบสนองในสภาพแวดล้อม
เพื่อขยายแนวคิดนี้ มาดูเสียง 3D แบบช็อตเดียวจากตัวอย่าง Plant สำหรับขั้นตอนของการปลูกกะหล่ำปลี:
- มีเสียงคลิกเบา ๆ เล่นเมื่อผู้เล่นปลูกเมล็ดพันธุ์
- มีเสียงแบบสาดน้ำเมื่อผู้เล่นรดน้ำต้นไม้ของพวกเขา
- มีเสียง "คลิป" เล่นเมื่อผู้เล่นเก็บเห็ดที่ครบกำหนด
- มีเสียง "ทุ่ม" เบา ๆ เมื่อผู้เล่นวางกะหล่ำไว้ในรถเข็น
เสียงเหล่านี้ช่วยเสริมการมีอยู่ของปุ่มการกระทำของผู้เล่น proximity prompt กับการมีปฏิสัมพันธ์ของการเปลี่ยนแปลงในพื้นที่ 3D สำหรับผู้เล่นที่มีปัญหาทางการมองเห็นซึ่งการเปลี่ยนสีหรือแอนิเมชั่นยากกว่าที่จะพิเคราะห์ค่อนข้างจะเป็นการให้ฟีดแบ็กที่หลากหลายช่วยให้การโต้ตอบกับวัตถุ 3D มีการเข้าถึงและเป็นธรรมชาติสำหรับผู้เล่นมากที่สุด
เพื่อให้ตัวอย่างที่แตกต่างของการกำหนดการโต้ตอบกับวัตถุพร้อมฟีดแบ็กหลายประเภท ตัวอย่างนี้จัดให้มีฟีดแบ็กทั้งสิ่งมองเห็นและเสียงทุกครั้งที่ผู้เล่นเหยียบปุ่ม 3D ลูกอมข้าวในบ้านขนมปังขิง เมื่อผู้เล่นไม่ได้มีปฏิสัมพันธ์กับปุ่ม มันก็จะปรากฏว่าคือขนมลูกอมทั่วไป แต่เมื่อพวกเขาเหยียบปุ่ม ตัวอย่างนี้:
- เล่นแทร็กเสียงที่เฉลิมฉลอง
- เปลี่ยนสีด้านข้างของปุ่มไปเป็นสีเขียว
- เคลื่อนที่ปุ่มดำเข้าสู่พื้น
จากที่นี่ คุณสามารถเชื่อมโยงการโต้ตอบนี้กับการกระทำที่เกมแข่งขันอื่น ๆ ได้หลายรูปแบบ เช่น การปลดล็อควัตถุหรือการกระตุ้นความสามารถพิเศษ


ในการสร้างเสียง 3D แบบช็อตเดียวสำหรับการโต้ตอบกับวัตถุในไฟล์ตัวอย่าง Gingerbread House - Complete Audio:
ในหน้าต่าง Explorer ให้ไปที่ Workspace ⟩ 3DAudioButton, จากนั้น:
- แทรกวัตถุ AudioPlayer เพื่อสร้างแหล่งเสียงสำหรับปุ่ม
- แทรกวัตถุ AudioEmitter เพื่อปล่อยเสียงเชิงตำแหน่งจาก 3DAudioButton
- แทรกวัตถุ Wire เพื่อพาเสียงจาก AudioPlayer ไปยัง AudioEmitter

เลือก AudioPlayer แล้วในหน้าต่าง Properties ตั้งค่า AssetID เป็น rbxassetid://1846248593 เพื่อเล่นแทร็กเสียงที่เฉลิมฉลองเต็มไปด้วยความสุข
เลือก Wire แล้วในหน้าต่าง Properties,
- ตั้งค่า SourceInstance เป็น AudioPlayer ใหม่ของคุณเพื่อระบุว่าคุณต้องการให้สายไฟนำเสียงจากผู้เล่นเสียงนี้
- ตั้งค่า TargetInstance เป็น AudioEmitter ใหม่ของคุณเพื่อระบุว่าคุณต้องการให้สายไฟนำเสียงไปยังผู้ปล่อยเสียงที่เฉพาะเจาะจงในปุ่มนี้
กลับไปที่หน้าต่าง Explorer แทรก Script ลงใน 3DAudioButton, เปลี่ยนชื่อเป็น PlayAudioWhenPressed, แล้ววางโค้ดต่อไปนี้ลงในสคริปต์:
local TweenService = game:GetService("TweenService")local buttonModel = script.Parent.Parentlocal buttonPart = buttonModel.ButtonPartlocal buttonPressedAudioPlayer = buttonModel.ButtonPressedAudioPlayerlocal tweenInfo = TweenInfo.new(.2, Enum.EasingStyle.Exponential)local buttonTweenByIsPressed = {-- กด[true] = TweenService:Create(buttonPart, tweenInfo, {Size = buttonPart.Size / Vector3.new(2, 1, 1),Color = Color3.fromRGB(75, 151, 75),}),-- ค่าเริ่มต้น[false] = TweenService:Create(buttonPart, tweenInfo, {Size = buttonPart.Size,Color = Color3.fromRGB(196, 40, 28),}),}local function onIsPlayingChanged()local isPlaying = buttonPressedAudioPlayer.IsPlayinglocal tween = buttonTweenByIsPressed[isPlaying]tween:Play()endonIsPlayingChanged()buttonPressedAudioPlayer:GetPropertyChangedSignal("IsPlaying"):Connect(onIsPlayingChanged)buttonPressedAudioPlayer.Ended:Connect(onIsPlayingChanged)buttonPart.Touched:Connect(function(_hit)buttonPressedAudioPlayer:Play()end)คำอธิบายโค้ดสคริปต์เริ่มต้นโดยการดึงออก:
- TweenService เพื่อให้สามารถสร้างการเคลื่อนไหวให้กับพาร์ตปุ่มที่อยู่ในพื้นดิน
- โมเดลพ่อแม่ 3DAudioButton ของสคริปต์
- ส่วนของปุ่มที่ยื่นออกมาจากพื้น
- ผู้เล่นที่เกี่ยวข้องซึ่งเป็นเสียงบรรยายของการเฉลิมฉลอง
จากนั้นสคริปต์จะกำหนด:
- วัตถุ TweenInfo ที่ระบุว่าวิธีการเคลื่อนไหวของปุ่มจะเล่นด้วยรูปแบบการเคลื่อนไหวแบบเชิงพาณิชย์
- สองการ์ดที่แทนค่าลักษณะของปุ่มที่กดหรือไม่กด
- สถานะกด true ทำให้ปุ่มเคลื่อนที่ตัวลงไปด้านล่างเล็กน้อยลงไปในพื้น และเปลี่ยนสีของพาร์ตไปเป็นสีเขียว
- สถานะไม่กด false ทำให้ปุ่มเคลื่อนกลับไปยังตำแหน่งเดิมและลบสีที่เปลี่ยน
ส่วนที่เหลือของสคริปต์คือจุดที่ทำงานมากที่สุดของฟีดแบ็กการโต้ตอบกับวัตถุ พูดถึงวิธีการทำงานร่วมกันของฟังก์ชัน onIsPlayingChanged และตัวจัดการเหตุการณ์:
- buttonPart.Touched ฟังการแตะของผู้เล่นบนปุ่ม จากนั้นเรียกใช้ฟังก์ชัน Play() เพื่อเริ่มเล่นเสียงที่เกี่ยวข้องจากผู้เล่นเสียง สิ่งนี้ทำให้เปลี่ยนสถานะ AudioPlayer.IsPlaying จาก false เป็น true
- buttonPressedAudioPlayer:GetPropertyChangedSignal("IsPlaying") ฟังการเปลี่ยนแปลงของสถานะ IsPlaying ของผู้เล่นเสียง จากนั้นเรียกใช้ฟังก์ชัน onIsPlayingChanged
- ฟังก์ชัน onIsPlayingChanged ใช้ข้อมูลนี้เพื่อกระตุ้นการเคลื่อนไหวที่เปลี่ยนรูปลักษณ์ในพื้นที่ 3D
- เพื่อหลีกเลี่ยงผู้เล่นจากการเริ่มการเล่นเสียงใหม่ถ้าพวกเขาไปยืนบนปุ่มในระยะเวลาอันรวดเร็ว buttonPressedAudioPlayer.Ended ฟังเสียงยนต์ของเสียงเพื่อสิ้นสุดการเล่นก่อนที่จะเรียกใช้ฟังก์ชัน onIsPlayingChanged อีกครั้ง
สิ่งสำคัญที่จะต้องทราบคือเหตุการณ์ onIsPlayingChanged จะเกิดขึ้นเฉพาะเมื่อสถานะที่เปลี่ยนจาก false เป็น true ซึ่งหมายความว่าไม่เกิดขึ้นเมื่อเปลี่ยนจาก true เป็น false ซึ่งคาดหวังจะเกิดขึ้นตามเวลาของการตอบสนองจากเซิร์ฟเวอร์ไปยังไคลเอนต์ เนื่องจากเหตุผลนี้ เหตุการณ์ Ended จะถูกอธิบายและฟังอยู่ในตัวอย่างนี้เพื่อครอบคลุมทั้งสองกรณี
ทดสอบเล่นประสบการณ์เพื่อฟังเสียงเฉลิมฉลองเมื่อตัวละครผู้เล่นของคุณสัมผัสปุ่ม 3D ในบ้านขนมปังขิง เมื่อคุณเดินออกไปจากปุ่ม ระดับเสียงจะลดลง
บทสนทนาของตัวละคร
การให้เสียงเชิงทิศทางจากตัวละครที่ไม่สามารถเล่นได้ (NPC) เป็นประโยชน์ที่จะช่วยแนะนำผู้เล่นไปยังจุดที่น่าสนใจในสภาพแวดล้อมของพวกเขา และเพิ่มความลึกซึ้งให้กับการโต้ตอบของพวกเขากับตัวละครอื่น ๆ ในความเป็นจริง ในประสบการณ์ที่มีเนื้อเรื่อง หลาย ๆ นักออกแบบใช้บทสนทนาของตัวละครอย่างมีกลยุทธ์เพื่อสอนผู้เล่นเกี่ยวกับตัวละคร ทั้งในด้านลักษณะของตัวละครและอื่น ๆ
ตัวอย่างทั่วไปของเทคนิคนี้ได้แก่:
- สไตล์บทสนทนา เพื่อสร้างบรรยากาศของประสบการณ์
- การพูดคุย เพื่อสอนผู้เล่นเกี่ยวกับความสัมพันธ์ของตัวละคร
- การพูดคุยของศัตรู เพื่อเปิดเผยแรงจูงใจหรือตำแหน่งของพวกเขาในความสัมพันธ์กับผู้เล่น
- ตัวละครพูดความคิดของตนออกมา เพื่อแนะนำผู้เล่นในสิ่งที่พวกเขาควรทำถัดไป เช่น การฟื้นฟูตัวเอง การเคลื่อนย้ายไปยังตำแหน่งอื่น หรือการหาไอเท็ม
- ตัวละครที่เป็นพันธมิตรกำลังพูดคุยกับตัวละครผู้เล่น เพื่อเปิดเผยรายละเอียดเกี่ยวกับโลกภายในประสบการณ์ เช่น ประวัติศาสตร์ วัฒนธรรม และปัญหาสังคม
เพื่อแสดงให้เห็นว่านี่อาจทำในทางปฏิบัติได้อย่างไร มาดูเสียง 3D แบบช็อตเดียวจาก Beyond the Dark ที่เล่นเป็นระยะ ๆ เมื่อผู้เล่นอยู่ในพื้นที่ล็อบบี้หลักของสถานีอวกาศ
การใช้สถานีอวกาศเป็นตัวละคร คลิปบทสนทนานี้ให้ผู้เล่นข้อมูลที่สำคัญและเนื้อเรื่องเกี่ยวกับสถานที่โดยรวม ตัวอย่างเช่น จากประโยคเดียวนี้ ผู้เล่นจะได้เรียนรู้:
- พวกเขาอยู่ในอวกาศ โดยเฉพาะอย่างยิ่งในสถานีอวกาศที่ชื่อว่า Kerr-Newman Deep Space Relay 14
- สภาพแวดล้อมของพวกเขามีลักษณะอนาคตและพร้อมต้อนรับ
- พวกเขาเป็นผู้เยือนและน่าจะออกไปในไม่ช้า
รายละเอียดเหล่านี้ช่วย immerse ผู้เล่นในสภาพแวดล้อมของพวกเขา และให้ความรู้สึกเร่งด่วนในการทำภารกิจของพวกเขา อย่างไรก็ตาม หากผู้เล่นไม่ทราบว่าภารกิจหลักของพวกเขาคืออะไร คุณสามารถใช้บทสนทนาของตัวละครเพื่อแจ้งผู้เล่นเกี่ยวกับสิ่งที่คุณต้องการให้พวกเขาทำในประสบการณ์ของคุณ
เพื่อแสดงตัวอย่าง ตัวอย่างนี้ใช้ พื้นที่ หรือพื่นที่ที่มองไม่เห็นภายในพื้นที่ 3D เพื่อกระตุ้นบทสนทนาของตัวละครจากมนุษย์หิมะเพื่อแนะนำผู้เล่นให้เก็บรวบรวมลูกอมสามลูกเพื่อเปิดประตูบ้านของเขา เป็นสิ่งแรกที่ผู้เล่นเห็นเมื่อเข้าร่วมประสบการณ์ ผู้เล่นจะมีแนวโน้มที่จะกระตุ้นบทสนทนาและรู้ว่าพวกเขาต้องทำอะไรเพื่อให้ประสบความสำเร็จ

ในการสร้างเสียง 3D แบบช็อตเดียวสำหรับบทสนทนาของตัวละครในไฟล์ตัวอย่าง Gingerbread House - Complete Audio:
ในหน้าต่าง Explorer ให้ไปที่ Workspace ⟩ DialogueVolume, จากนั้น:
- แทรกวัตถุ AudioPlayer เพื่อสร้างแหล่งเสียงสำหรับพื้นที่
- แทรกวัตถุ AudioEmitter เพื่อปล่อยเสียงเชิงตำแหน่งจาก DialogueVolume
- แทรกวัตถุ Wire เพื่อพาเสียงจาก AudioPlayer ไปยัง AudioEmitter

เลือก AudioPlayer แล้วในหน้าต่าง Properties ตั้งค่า AssetID เป็น rbxassetid://92917410841704 เพื่อเล่นเสียงแจ้งเตือนวัตถุของประสบการณ์
เลือก Wire แล้วในหน้าต่าง Properties,
- ตั้งค่า SourceInstance เป็น AudioPlayer ใหม่ของคุณเพื่อระบุว่าคุณต้องการให้สายไฟนำเสียงจากผู้เล่นเสียงนี้
- ตั้งค่า TargetInstance เป็น AudioEmitter ใหม่ของคุณเพื่อระบุว่าคุณต้องการให้สายไฟนำเสียงไปยังผู้ปล่อยเสียงที่เฉพาะเจาะจงในพื้นที่นี้
กลับไปที่หน้าต่าง Explorer ให้ไปที่ StarterPlayer ⟩ StarterCharacterScripts, แทรก LocalScript, เปลี่ยนชื่อเป็น PlayAudioWhenInVolume, แล้ววางโค้ดต่อไปนี้ลงในสคริปต์:
local Workspace = game:GetService("Workspace")local Players = game:GetService("Players")local humanoid = script.Parent:WaitForChild("Humanoid")local volumeDetector = Workspace.DialogueVolumelocal trigger = humanoid:WaitForChild("Animator")local debounce = falselocal localPlayer = Players.LocalPlayervolumeDetector.Touched:Connect(function(hit)if debounce thenreturnendlocal hitCharacter = hit:FindFirstAncestorWhichIsA("Model")local hitPlayer = Players:GetPlayerFromCharacter(hitCharacter)if hitPlayer ~= localPlayer thenreturnenddebounce = truelocal audioPlayer = Workspace.DialogueVolume.AudioPlayeraudioPlayer:Play()audioPlayer.Ended:Wait()debounce = falseend)คำอธิบายโค้ดสคริปต์นี้เริ่มต้นโดยการดึงบริการ Workspace และ Players เพื่อให้สามารถอ้างอิงลูกและฟังก์ชันของพวกเขา สำหรับผู้เล่นแต่ละคนที่โหลดหรือฟื้นฟูกลับเข้าสู่ประสบการณ์ สคริปต์จะรอให้:
- วัตถุพื้นที่ใน Workspace ชื่อว่า DialogueVolume
เมื่อใดก็ตามที่มีสิ่งใด ๆ ชนเข้ากับพื้นที่ ตัวจัดการเหตุการณ์ Touched ฟังก์ชั่นจะได้รับมือถือที่เป็น Ancestor แรกที่เป็น Model ซึ่งควรจะเป็นตัวละครเมื่อ BasePart ที่ชนกับพื้นที่คือเป็นอนุกรมของโมเดลตัวละคร ถ้าเป็นเช่นนั้น ฟังก์ชันก็จะ:
- ตั้งค่า debounce เป็น true
- เล่นและรอให้เสียงสิ้นสุด
- ตั้งค่า debounce กลับเป็น false
การตั้งค่า debounce จาก false เป็น true และกลับเป็น false อีกครั้งหลังจากเสียงเล่นจบ เป็นรูปแบบการทำงานที่ป้องกันเสียงจากการเรียกซ้ำเมื่อผู้เล่นสัมผัสเข้ากับพื้นที่อย่างต่อเนื่อง สำหรับข้อมูลเพิ่มเติมเกี่ยวกับรูปแบบการทำงานนี้ ดูที่ Debounce - Detect collisions.
ทดสอบเล่นประสบการณ์เพื่อฟังบทสนทนาการแจ้งเตือนเมื่อตัวละครของคุณสัมผัสพื้นที่รอบ ๆ มนุษย์หิมะ