3D 오디오는 3D 공간의 특정 위치에서 방출되는 방향성 소리로, 오디오 발신자와 청취자 간의 거리와 방향에 따라 볼륨이 증가하거나 감소합니다. 이는 청취자나 발신자가 환경을 돌아다닐 때, 플레이어가 다양한 방향과 볼륨 레벨에서 그 오디오를 동적으로 들을 수 있음을 의미합니다.
Gingerbread House - Start .rbxl 파일을 시작점으로 사용하고 Gingerbread House - Complete Audio를 참조하여, 이 튜토리얼에서는 게임에 루프 및 원샷 3D 오디오를 추가하는 방법을 보여주며, 다음과 같은 지침을 포함합니다:
- 플레이어가 서버에 연결되자마자 재생되는 루프 환경 소리.
- 플레이어의 게임 플레이에 중요한 주요 상황 이벤트에 대해 알리기 위해 오디오를 트리거하는 방법.
- 3D 객체와 상호작용할 때 플레이어에게 청각적 피드백을 제공하기 위해 오디오를 활성화하는 방법.
- 플레이어를 환경 내의 관심 지점으로 유도하는 캐릭터 사운드 바이트 재생.
과정 중에 막히는 부분이 있다면, Gingerbread House - Complete Audio를 참조하여 진행 상황을 비교할 수 있습니다.
오디오 객체
방향성 오디오를 생성하려면 이 튜토리얼 전반에 걸쳐 작업할 오디오 객체를 이해하는 것이 중요합니다. 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 스터드마다 볼륨이 감소합니다. 이는 실제 세계에서 소리가 원천에서 멀어질수록 볼륨이 감소하는 것을 모방합니다.
샘플 Gingerbread House - Complete Audio 장소 파일에서 루프 3D 오디오를 재현하려면:
플레이어 캐릭터에 연결된 기본 리스너를 활성화합니다.
- Explorer 창에서 SoundService를 선택합니다.
- Properties 창에서 DefaultListenerLocation을 Character로 설정합니다. 게임을 실행하면 엔진이 자동으로:
- 각 플레이어 캐릭터의 Humanoid.RootPart 아래에 AudioListener를 생성하여 게임 내 소리의 위치와 크기에 따라 실제 스피커에서 소리가 이동하는 것을 들을 수 있습니다.
- SoundService 아래에 AudioDeviceOutput을 생성합니다.
Explorer 창에서 Workspace ⟩ WaterfallAudioObject로 이동한 후:
- 폭포를 위한 오디오 소스를 생성하기 위해 AudioPlayer 객체를 삽입합니다.
- WaterfallAudioObject에서 위치 스트림을 방출하기 위해 AudioEmitter 객체를 삽입합니다.
- 오디오 플레이어에서 오디오 발신자로 스트림을 전달하기 위해 Wire 객체를 삽입합니다.

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 창으로 돌아가 WaterfallAudioObject에 Script를 삽입하고 이름을 LoopWaterfallMusic으로 변경한 후, 다음 코드를 스크립트에 붙여넣습니다:
local audioPlayer = script.ParentaudioPlayer:Play()코드 설명이 스크립트는 스크립트의 부모 AudioPlayer를 나타내는 변수를 선언하는 것으로 시작합니다. 그런 다음 스크립트는 플레이어가 게임에 참여하는 순간부터 게임을 종료할 때까지 오디오 소스를 재생하도록 설정합니다.
게임을 플레이 테스트하여 아바타가 폭포 근처에 있을 때 루프 초콜릿 비 소리를 들으세요. 캐릭터의 머리를 다른 방향으로 돌리면 소리가 3D 공간 내 발신자의 위치에 따라 실제 스피커에서 동적으로 이동합니다.
원샷 오디오
원샷 3D 오디오는 특정 시간과 위치에서 한 번 재생되는 방향성 오디오로, 플레이어가 다시 트리거하지 않는 한 재생됩니다. 이는 플레이어에게 그들의 행동, 환경 및 주변 캐릭터에 대한 맥락을 제공합니다. 게임에서 이러한 유형의 청각적 피드백을 사용하는 것은 필수적입니다. 왜냐하면 플레이어가 적을 피하거나 유용한 아이템을 수집하는 등의 전략적 결정을 내릴 수 있도록 도와주기 때문입니다.
다음 섹션에서는 플레이어가 시기적절하고 방향성 피드백이 필요한 일반적인 게임 플레이 시나리오에 대한 구현 세부정보를 제공합니다. 여기에는 상황별 게임 플레이 이벤트, 객체 상호작용 및 비플레이어 캐릭터 대화가 포함됩니다.
이벤트 피드백
플레이어가 새로운 게임 플레이 영역을 잠금 해제하거나 적의 사격을 유도하는 등 환경 내에서 주요 상황 이벤트를 트리거할 때, 그들이 3D 공간에서 어디에 집중하고 주의를 기울여야 하는지를 이해하는 것이 중요합니다. 즉각적인 청각적 피드백을 받지 못하면, 플레이어는 게임 플레이에 중요한 정보를 놓칠 수 있으며, 다음에 어디로 가야 할지 또는 무엇을 해야 할지 모르는 것에 대한 불만을 느낄 수 있습니다.
이것이 중요한 이유를 시연하기 위해, Laser Tag 템플릿에서 각 플레이어의 블래스터에서 재생되는 원샷 3D 오디오를 검토해 보겠습니다:
- 플레이어가 블래스터에서 발사할 때마다 깊은 팝 소리가 재생됩니다.
- 플레이어가 블래스터에 새로운 라운드를 장전할 때마다 클릭 소리와 로봇 비프 소리가 재생됩니다.
이 두 소리는 모두 주변 플레이어에게 발사 방향을 알림으로써 상황 인식을 제공합니다. 이를 통해 플레이어는 재미에 참여하거나 잠재적인 위험을 피하는 등의 정보에 기반한 결정을 내릴 수 있습니다.
샘플은 이 기술을 사용하여 플레이어가 게임 내 주요 목표를 완료했을 때 보상을 인식할 수 있도록 합니다. 플레이어가 세 개의 구름 사탕을 모두 수집하면, 생일 케이크의 문이 열려 플레이어가 내부의 선물에 접근할 수 있게 됩니다.
플레이어가 구름 사탕을 수집하는 데 특정한 순서가 없기 때문에, 플레이어가 마지막으로 어떤 구름 사탕을 수집하든 문이 열리는 것을 인식하는 것이 중요합니다. 위치 소리는 플레이어가 성공을 인식하고 문으로 가야 할 위치를 알 수 있도록 합니다.
샘플 Gingerbread House - Complete Audio 장소 파일에서 원샷 이벤트 피드백 3D 오디오를 재현하려면:
Explorer 창에서 Workspace ⟩ Door로 이동한 후:
- 볼륨을 위한 오디오 소스를 생성하기 위해 AudioPlayer 객체를 삽입합니다.
- Door에서 위치 스트림을 방출하기 위해 AudioEmitter 객체를 삽입합니다.
- 오디오 플레이어에서 오디오 발신자로 스트림을 전달하기 위해 Wire 객체를 삽입합니다.

AudioPlayer를 선택한 후, Properties 창에서 AssetID를 rbxassetid://5930776613로 설정하여 슬라이딩 금속 게이트 오디오 트랙을 재생합니다.
Wire를 선택한 후, Properties 창에서,
- SourceInstance를 새 AudioPlayer로 설정하여 이 특정 오디오 플레이어에서 오디오를 전달하도록 지정합니다.
- TargetInstance를 새 AudioEmitter로 설정하여 볼륨 내 이 특정 오디오 발신자로 오디오를 전달하도록 지정합니다.
Explorer 창으로 돌아가 ServerScriptService로 이동한 후, Script를 삽입하고 이름을 GumdropService로 변경한 후, 다음 코드를 스크립트에 붙여넣습니다:
-- 변수 초기화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-- 이벤트 리스너 설정for _, gumdrop in gumdrops dogumdrop:SetAttribute("Enabled", true)gumdrop.Touched:Connect(function(otherPart)onGumdropTouched(otherPart, gumdrop)end)end코드 설명이 스크립트는 Workspace, Players, ServerStorage, 및 TweenService 서비스를 초기화하여 자식 및 기능을 참조할 수 있도록 합니다. 그런 다음, ServerStorage에서 Leaderboard 및 PlayerData 모듈을 요구합니다. 이 모듈은 환경에서 플레이어가 수집한 구름 사탕의 양을 추적하는 리더보드를 화면의 오른쪽 상단에 생성하고 업데이트하는 역할을 합니다.
스크립트의 updatePlayerGumdrops 함수는 이벤트 피드백을 위한 3D 오디오를 트리거하는 작업의 대부분이 발생하는 곳이며, 두 개의 인수를 받습니다:
- player - 구름 사탕을 수집하는 플레이어.
- updateFunction - 플레이어의 수집한 구름 사탕 양을 업데이트하는 콜백 함수.
플레이어가 구름 사탕과 충돌할 때, 스크립트는:
- PlayerData.updateValue 함수를 호출하여 플레이어의 새로운 구름 사탕 수집 양 값을 가져옵니다.
- Leaderboard.setStat 함수를 호출하여 이 새로운 양으로 리더보드를 업데이트합니다.
- 양이 3 이상인지 확인합니다.
이 값이 3 이상일 경우, 스크립트는:
- 오디오 플레이어에서 오디오 발신자로 3D 오디오 트랙을 재생합니다.
- 문을 현재 위치에서 15 스터드 아래로 선형적으로 이동시킵니다.
나머지 스크립트는 구름 사탕과 충돌하는 모든 것을 감지하여 플레이어인지 확인하고 수집 피드백을 위한 비위치 소리를 트리거하는 역할을 합니다. 이 스크립트의 이 부분에 대한 자세한 내용은 2D 오디오 추가 - 게임 플레이 피드백을 참조하세요.
게임을 플레이 테스트하여 환경에서 세 개의 구름 사탕을 모두 수집한 후 슬라이드 게이트 소리를 들으세요. 카메라를 회전하면 소리가 3D 공간 내 발신자의 위치에 따라 실제 스피커에서 동적으로 이동합니다.
객체 상호작용
플레이어가 조명 스위치를 켜거나 무기를 집는 등 환경 내 3D 객체와 상호작용할 때, 그들이 객체와 상호작용하는 방법을 직관적으로 이해할 수 있도록 즉각적인 피드백을 제공하는 것이 중요합니다. 시각적 피드백과 청각적 피드백의 조합은 플레이어의 행동과 환경 반응 간의 인과 관계를 강화합니다.
이 개념을 확장하기 위해, Plant 샘플에서 양배추를 재배하는 사용자 흐름에 대한 원샷 3D 오디오를 검토해 보겠습니다:
- 플레이어가 씨앗을 심을 때 부드러운 클링 소리가 재생됩니다.
- 플레이어가 자라는 식물에 물을 줄 때 젖은 물소리 같은 소리가 재생됩니다.
- 플레이어가 완전히 자란 식물을 수확할 때 클립 소리가 재생됩니다.
- 플레이어가 양배추를 수레에 넣을 때 부드러운 쿵 소리가 재생됩니다.
이 모든 소리는 3D 공간에서 형태가 변하는 객체와의 플레이어의 근접 프롬프트 주요 상호작용을 강화합니다. 색상 변화나 애니메이션을 스스로 해석하기 어려운 시각 장애가 있는 플레이어에게 이러한 여러 형태의 감각 피드백을 제공하면 3D 객체 상호작용이 가능한 한 많은 플레이어에게 접근 가능하고 직관적으로 유지됩니다.
객체 상호작용에 대한 여러 형태의 감각 피드백을 구성하는 방법에 대한 다른 예를 제공하기 위해, 샘플은 플레이어가 생강빵 집 내 3D 페퍼민트 버튼을 밟을 때마다 시각적 및 청각적 피드백을 제공합니다. 플레이어가 버튼과 상호작용하지 않을 때, 버튼은 일반적인 페퍼민트 사탕처럼 보이지만, 버튼을 밟으면 샘플은:
- 축하하는 징글 오디오 트랙을 재생합니다.
- 버튼의 측면을 녹색으로 색칠합니다.
- 버튼을 땅으로 이동시킵니다.
여기서 이 상호작용을 아이템 잠금 해제나 특별 능력 트리거와 같은 다양한 독특한 게임 플레이 행동에 연결할 수 있습니다.


샘플 Gingerbread House - Complete Audio 장소 파일에서 원샷 객체 상호작용 3D 오디오를 재현하려면:
Explorer 창에서 Workspace ⟩ 3DAudioButton으로 이동한 후:
- 버튼을 위한 오디오 소스를 생성하기 위해 AudioPlayer 객체를 삽입합니다.
- 3DAudioButton에서 위치 스트림을 방출하기 위해 AudioEmitter 객체를 삽입합니다.
- 오디오 플레이어에서 오디오 발신자로 스트림을 전달하기 위해 Wire 객체를 삽입합니다.

AudioPlayer를 선택한 후, Properties 창에서 AssetID를 rbxassetid://1846248593로 설정하여 경쾌하고 축하하는 오디오 트랙을 재생합니다.
Wire를 선택한 후, Properties 창에서,
- SourceInstance를 새 AudioPlayer로 설정하여 이 특정 오디오 플레이어에서 오디오를 전달하도록 지정합니다.
- TargetInstance를 새 AudioEmitter로 설정하여 버튼 내 이 특정 오디오 발신자로 오디오를 전달하도록 지정합니다.
Explorer 창으로 돌아가 3DAudioButton에 Script를 삽입하고 이름을 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)로부터 방향성 오디오를 제공하는 것은 플레이어가 환경 내의 관심 지점으로 안내하고 다른 캐릭터와의 상호작용에 깊이를 더하는 데 도움이 됩니다. 사실, 내러티브 중심의 게임에서 많은 디자이너는 캐릭터 대화를 전략적으로 사용하여 플레이어에게 캐릭터, 동맹 및 적 캐릭터 또는 세계 자체에 대해 간접적으로 가르칩니다.
이 기술의 일반적인 예는 다음과 같습니다:
- 대화 스타일로 게임의 톤을 설정합니다.
- 농담으로 캐릭터 관계에 대해 플레이어에게 가르칩니다.
- 적 대화로 동기나 플레이어와의 관계를 고백합니다.
- 플레이어 캐릭터가 자신의 생각을 소리 내어 말하기로 플레이어가 다음에 무엇을 해야 하는지 부드럽게 안내합니다. 예를 들어, 자신을 치유하거나 다른 위치로 이동하거나 아이템을 찾는 것입니다.
- 동맹 캐릭터가 플레이어 캐릭터와 대화하여 게임 내 세계의 역사, 문화 및 사회 문제와 같은 세부 정보를 드러냅니다.
이것이 실제로 어떻게 보일 수 있는지를 시연하기 위해, Beyond the Dark 쇼케이스에서 주기적으로 재생되는 원샷 3D 오디오를 검토해 보겠습니다. 이 오디오는 플레이어가 우주 정거장의 주요 로비 지역에 있을 때 재생됩니다.
우주 정거장을 캐릭터로 사용하여, 이 대화 클립은 플레이어에게 전체 설정에 대한 중요한 맥락과 전설을 제공합니다. 예를 들어, 이 한 문장에서 플레이어는 다음을 알게 됩니다:
- 그들은 우주에 있으며, 특히 Kerr-Newman Deep Space Relay 14라는 우주 정거장에 있습니다.
- 그들의 환경은 미래적이고 환영합니다.
- 그들은 방문자이며 곧 떠날 가능성이 높습니다.
이러한 세부 사항은 함께 플레이어를 환경에 몰입시키고 그들의 임무에 대한 긴박감을 더합니다. 그러나 플레이어가 자신의 주요 임무가 무엇인지 모른다면, 캐릭터 대화를 사용하여 게임 내에서 플레이어가 무엇을 해야 하는지를 알릴 수도 있습니다.
예를 들어, 샘플은 볼륨 또는 3D 공간 내의 보이지 않는 영역을 사용하여 눈사람으로부터 캐릭터 대화를 트리거하여 플레이어가 세 개의 구름 사탕을 수집하여 그의 집의 문을 열도록 안내합니다. 플레이어가 게임에 참여할 때 가장 먼저 보는 것 중 하나이기 때문에, 플레이어는 대화를 트리거하고 성공하기 위해 무엇을 해야 하는지를 알 가능성이 높습니다.

샘플 Gingerbread House - Complete Audio 장소 파일에서 원샷 캐릭터 대화 3D 오디오를 재현하려면:
Explorer 창에서 Workspace ⟩ DialogueVolume으로 이동한 후:
- 볼륨을 위한 오디오 소스를 생성하기 위해 AudioPlayer 객체를 삽입합니다.
- DialogueVolume에서 위치 스트림을 방출하기 위해 AudioEmitter 객체를 삽입합니다.
- 오디오 플레이어에서 오디오 발신자로 스트림을 전달하기 위해 Wire 객체를 삽입합니다.

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 서비스를 가져와 자식 및 기능을 참조할 수 있도록 합니다. 각 플레이어 캐릭터가 게임에 로드되거나 다시 생성될 때, 스크립트는 다음을 기다립니다:
- DialogueVolume이라는 이름의 작업 공간 내 볼륨 객체.
볼륨과 충돌하는 모든 것이 있을 때, Touched 이벤트 핸들러 함수는 충돌한 볼륨과 관련된 첫 번째 조상을 Model로 가져옵니다. 이는 충돌한 BasePart가 캐릭터 모델의 자식인 경우 캐릭터가 되어야 합니다. 그렇다면 함수는 다음을 수행합니다:
- 디바운스를 true로 설정합니다.
- 오디오를 재생하고 끝날 때까지 기다립니다.
- 디바운스를 다시 false로 설정합니다.
디바운스를 false에서 true로, 다시 false로 설정하는 것은 플레이어가 볼륨과 지속적으로 충돌할 때 오디오가 반복적으로 트리거되는 것을 방지하는 디바운스 패턴입니다. 이 디바운스 패턴에 대한 자세한 내용은 디바운스 - 충돌 감지를 참조하세요.
게임을 플레이 테스트하여 플레이어 캐릭터가 눈사람 주변의 볼륨에 닿을 때 지침 캐릭터 대화를 들으세요.