2D 오디오 추가

*이 콘텐츠는 AI(베타)를 사용해 번역되었으며, 오류가 있을 수 있습니다. 이 페이지를 영어로 보려면 여기를 클릭하세요.

2D 오디오는 특정 위치에서 방출되지 않는 비방향성 사운드로, 3D 공간에서 청취자의 위치나 방향에 관계없이 동일하게 유지됩니다. 이는 플레이어가 환경에서 리스너를 이동할 때, 그들이 바라보는 모든 방향에서 2D 오디오를 일관되게 들을 수 있음을 의미합니다.

Gingerbread House - Start .rbxl 파일을 시작점으로 사용하고 Gingerbread House - Complete Audio를 참조하여, 이 튜토리얼에서는 게임에 루프 및 원샷 2D 오디오를 추가하는 방법을 보여주며, 다음과 같은 지침을 포함합니다:

  • 플레이어가 서버에 연결되자마자 재생되는 루프 배경 음악.
  • 플레이어의 게임 목표에 따라 즉각적인 피드백을 제공하기 위해 오디오를 트리거하는 방법.
  • 다양한 사용자 인터페이스 상호작용을 나타내기 위해 여러 사운드를 활성화하는 방법.

과정 중에 막히는 부분이 있다면, Gingerbread House - Complete Audio를 참조하여 진행 상황을 비교할 수 있습니다.

2D 오디오 객체

비방향성 오디오를 생성하기 위해서는 이 튜토리얼 전반에 걸쳐 작업할 오디오 객체를 이해하는 것이 중요합니다. 2D 오디오에는 세 가지 주요 유형의 오디오 객체가 있습니다:

  • AudioPlayer 객체는 오디오 파일을 로드하고 재생합니다.
  • AudioDeviceOutput 객체는 스피커나 헤드폰과 같은 물리적 하드웨어 장치입니다.
  • Wires는 오디오 스트림을 한 객체에서 다른 객체로 전달합니다.

이 모든 오디오 객체는 파일 재생에서 각 플레이어의 하드웨어로 사운드를 전달하기 위해 함께 작동합니다. 이제 플레이어가 헤드셋을 착용하고 노트북으로 게임을 하는 예를 통해 이 작동 방식을 살펴보겠습니다:

  • AudioPlayer는 통화 구매 사운드를 위해 127645268874265 오디오 자산 ID를 게임에 로드합니다.
  • WireAudioPlayer에서 AudioDeviceOutput으로 스트림을 전달하여 플레이어의 헤드셋에서 소리가 나도록 합니다.
  • AudioDeviceOutput 객체는 소리를 플레이어의 물리적 스피커, 또는 이 경우에는 헤드폰으로 전달합니다.

다음 섹션에서는 이러한 객체를 더 깊이 살펴보며 루프 및 원샷 2D 오디오를 재생하는 방법을 배웁니다. 이러한 객체를 다루는 기술을 검토하면서 게임에서 플레이어에게 소리를 캡처하고 전달하는 방법을 더 정확하게 예측할 수 있습니다.

루프 오디오

루프 2D 오디오는 플레이어가 서버에 연결되자마자 매끄럽게 반복되는 비방향성 오디오로, 플레이어가 무엇을 하든지 또는 3D 공간 내에서 어디에 위치하든지 간에 일관된 청각 배경을 제공합니다. 또한, 루프 2D 오디오는 게임이 완전히 침묵하지 않도록 보장하여 플레이어가 목표에서 벗어나 혼란스러워지지 않도록 합니다.

이 개념을 설명하기 위해, 다음 2D 오디오가 Hazardous Space Station 샘플의 품질을 어떻게 향상시키는지 살펴보세요. 배경 음악이 없으면 우주 정거장은 텅 비고 생명이 없는 느낌을 줍니다. 그러나 우주 정거장에 배경 음악이 포함되면, 정거장은 불길하고 위험한 느낌을 주어 전체적인 으스스한 분위기를 더합니다.

루프 없는 2D 오디오
루프 있는 2D 오디오

루프 오디오는 플레이어가 게임에 들어오자마자 느끼고 싶은 감정을 설정하는 데 특히 유용합니다. 예를 들어, 샘플은 플레이어에게 겨울 원더랜드에서 즐거운 모험을 제공하는 것을 목표로 하므로, 플레이어가 환경에 들어서는 순간 긍정적인 기분을 주기 위해 경쾌한 오디오 트랙을 사용합니다. 이 기술이 얼마나 영향력이 있는지 보려면, 루프 오디오를 금속 트랙으로 바꿨을 때 플레이어의 경험이 어떻게 변할지를 고려해 보세요.

샘플 Gingerbread House - Complete Audio 장소 파일에서 루프 2D 오디오를 재현하려면:

  1. 플레이어 캐릭터에 연결된 기본 리스너를 활성화합니다.

    1. Explorer 창에서 SoundService를 선택합니다.
    2. Properties 창에서 DefaultListenerLocationCharacter로 설정합니다. 게임을 실행하면 엔진이 자동으로 SoundService 아래에 AudioDeviceOutput을 생성합니다.
  2. Explorer 창에서 SoundService로 이동한 후:

    1. 오디오 소스를 생성하기 위해 AudioPlayer 객체를 삽입합니다.
    2. 게임 전반에 걸쳐 재생되는 스피커를 생성하기 위해 AudioDeviceOutput 객체를 삽입합니다.
    3. 오디오 플레이어에서 스피커로 스트림을 전달하기 위해 Wire 객체를 삽입합니다.
  3. AudioPlayer를 선택한 후, Properties 창에서,

    1. AssetIDrbxassetid://1841461968로 설정하여 경쾌한 오디오 트랙을 재생합니다.
    2. Looping을 활성화하여 오디오가 매끄럽게 반복되도록 합니다.
    3. Volume0.2로 설정하여 게임 내 다른 오디오 소스를 들을 수 있을 정도로 낮은 볼륨으로 재생합니다.
  4. Wire를 선택한 후, Properties 창에서,

    1. SourceInstance를 새 AudioPlayer로 설정하여 이 특정 오디오 플레이어에서 오디오를 전달하도록 지정합니다.
    2. TargetInstance를 새 AudioDeviceOutput으로 설정하여 이 특정 스피커로 오디오를 전달하도록 지정합니다.
  5. Explorer 창으로 돌아가 AudioPlayerScript를 삽입하고, 이름을 LoopBackgroundMusic으로 변경한 후, 다음 코드를 스크립트에 붙여넣습니다:

    local audioPlayer = script.Parent
    audioPlayer:Play()

    이 스크립트는 스크립트의 부모인 AudioPlayer를 나타내는 변수를 선언하는 것으로 시작합니다. 그런 다음, 플레이어가 게임에 들어오는 순간부터 게임을 종료할 때까지 오디오 소스를 재생하도록 설정합니다.

  6. 게임을 플레이 테스트하여 루프 배경 음악을 들으세요.

원샷 오디오

원샷 2D 오디오는 특정 시간과 위치에서 한 번 재생되며, 플레이어가 다시 트리거하지 않는 한 반복되지 않는 비방향성 오디오로, 플레이어가 놓치지 않기를 원하는 모든 것에 대한 중요한 맥락을 제공합니다. 게임에서 이러한 유형의 청각 피드백을 사용하는 것은 필수적입니다. 왜냐하면 이는 보스 전투 시작이나 상당한 양의 체력 손실과 같은 중요한 게임 플레이 기능 및 플레이어 행동에 대한 즉각적이고 명확한 반응을 제공하기 때문입니다.

다음 섹션에서는 플레이어가 시기적절한 비방향성 피드백이 필요한 일반적인 게임 플레이 시나리오에 대한 구현 세부정보를 제공합니다. 여기에는 게임 플레이 피드백, UI 요소 상호작용 및 튜토리얼을 위한 음성 내레이션이 포함됩니다.

게임 플레이 피드백

플레이어가 게임을 진행하면서, 점수, 체력 또는 레벨 진행 상황과 같이 게임 플레이에 영향을 미치는 모든 것의 상태에 대한 즉각적인 청각 피드백을 받는 것이 중요합니다. 이러한 유형의 오디오는 플레이어 목표와 직접 연결되므로, 이러한 소리가 명확하고 들리며 유용하고 정확한 정보를 전달하는 것이 중요합니다.

이 개념을 설명하기 위해, 플레이어가 점프하고 동전을 수집할 때 재생되는 Platformer 템플릿의 다음 원샷 2D 오디오를 살펴보겠습니다:

  • 플레이어가 장치에서 점프 키를 누르자마자 공기 중의 휙 소리가 재생됩니다.
  • 플레이어의 캐릭터가 동전에 닿자마자 높은 음의 딩 소리와 동전이 흔들리는 소리가 재생됩니다.

이 두 소리는 3D 공간의 맥락 내에서 즉시 인식 가능하며, 플레이어가 시각적 단서에만 의존하지 않고도 자신의 행동의 성공을 이해하는 데 도움을 줍니다.

여러 소리를 동시에 재생할 때, 특정 소리는 플레이어가 듣는 것이 더 중요할 수 있습니다. 이 경우, 동전 수집 소리는 점프 소리보다 더 가치 있는 게임 플레이 정보를 전달하므로, 게임은 이를 약간 더 높은 볼륨으로 재생합니다. 그러나 훌륭한 믹스를 달성하기 위한 표준이나 규칙은 없으므로, 게임 내 소리를 가장 중요하다고 느끼는 대로 조정하세요.

예를 들어, 샘플에는 게임 전반에 걸쳐 다양한 오디오 트리거가 포함되어 있지만, 이들은 게임의 주요 목표인 젤리빈을 수집하여 진저브레드 하우스를 여는 것에 대한 이해를 위해 모두 동일한 중요도를 가지지는 않습니다. 플레이어가 해야 할 일을 인식할 수 있도록 하기 위해, 샘플은 플레이어가 젤리빈을 수집할 때마다 청각 피드백의 진폭을 세 배로 늘립니다.

샘플 Gingerbread House - Complete Audio 장소 파일에서 원샷 상태 피드백 오디오를 재현하려면:

  1. Explorer 창에서 WorkspaceGumdropsGumdrop으로 이동한 후:

    1. 오디오 소스를 생성하기 위해 AudioPlayer 객체를 삽입합니다.
    2. 게임 전반에 걸쳐 재생되는 스피커를 생성하기 위해 AudioDeviceOutput 객체를 삽입합니다.
    3. 오디오 플레이어에서 스피커로 스트림을 전달하기 위해 Wire 객체를 삽입합니다.
  2. AudioPlayer를 선택한 후, Properties 창에서,

    1. AssetIDrbxassetid://9113723699로 설정하여 부드러운 씹는 소리 오디오 트랙을 재생합니다.
    2. TimePosition0.15로 설정하여 오디오 트랙이 실제 씹는 소리와 더 가까운 위치에서 시작되도록 합니다.
    3. Volume3으로 설정하여 게임 내 다른 오디오 소스보다 젤리빈 소리가 더 잘 들리도록 높은 볼륨으로 재생합니다.
  3. Wire를 선택한 후, Properties 창에서,

    1. SourceInstance를 새 AudioPlayer로 설정하여 이 특정 오디오 플레이어에서 오디오를 전달하도록 지정합니다.
    2. TargetInstance를 새 AudioDeviceOutput으로 설정하여 이 특정 스피커로 오디오를 전달하도록 지정합니다.
  4. Gumdrop을 세 개가 될 때까지 복제한 후, 환경에 흩어 놓습니다.

  5. 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.Gumdrops
    local gumdrops = gumdropsFolder:GetChildren()
    local GUMDROP_KEY_NAME = PlayerData.GUMDROP_KEY_NAME
    local GUMDROP_AMOUNT_TO_ADD = 1
    local 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.AudioPlayer
    audioPlayer:Play()
    -- 문을 아래로 이동시키는 애니메이션
    local doorPart = Workspace.Door
    local tweenInfo = TweenInfo.new(2, Enum.EasingStyle.Linear)
    local tween = TweenService:Create(doorPart, tweenInfo, {Position = doorPart.Position + Vector3.new(0, -15, 0)})
    tween:Play()
    end
    end
    -- 이벤트 핸들러 정의
    local function onGumdropTouched(otherPart, gumdrop)
    if gumdrop:GetAttribute("Active") then
    local character = otherPart.Parent
    local player = Players:GetPlayerFromCharacter(character)
    if player then
    -- 플레이어가 젤리빈에 닿음
    local audioPlayer = gumdrop.AudioPlayer
    audioPlayer:Play()
    gumdrop.Transparency = 1
    gumdrop:SetAttribute("Active", false)
    updatePlayerGumdrops(player, function(oldGumdropAmount)
    oldGumdropAmount = oldGumdropAmount or 0
    return oldGumdropAmount + GUMDROP_AMOUNT_TO_ADD
    end)
    end
    end
    end
    -- 이벤트 리스너 설정
    for _, gumdrop in gumdrops do
    gumdrop:SetAttribute("Active", true)
    gumdrop.Touched:Connect(function(otherPart)
    onGumdropTouched(otherPart, gumdrop)
    end)
    end

    이 스크립트는 Workspace, Players, ServerStorage, TweenService 서비스를 초기화하여 자식 및 기능을 참조할 수 있도록 합니다. 그런 다음, LeaderboardPlayerData 모듈을 ServerStorage에서 요구하여, 이 모듈들은 환경에서 플레이어가 수집한 젤리빈의 양을 추적하는 화면 오른쪽 상단의 리더보드를 생성하고 업데이트하는 역할을 합니다.

    스크립트의 updatePlayerGumdrops 함수는 플레이어가 젤리빈을 수집할 때마다 리더보드를 업데이트하고, 세 개의 젤리빈을 모두 수집할 때까지 기다려서 진저브레드 하우스의 문에 대한 위치 기반 소리와 애니메이션을 트리거하는 역할을 합니다. 이 스크립트의 이 부분에 대한 자세한 내용은 3D 오디오 추가 - 이벤트 피드백을 참조하세요.

    스크립트의 onGumdropTouched 함수는 게임 플레이 피드백을 위한 2D 오디오를 트리거하는 작업의 대부분이 발생하는 곳이며, 두 개의 인수를 받습니다:

    • otherPart - 젤리빈과 충돌하는 파트입니다.
    • gumdrop - 젤리빈을 나타내는 구형 파트입니다.

    젤리빈 파트와 충돌하는 모든 것에 대해, 스크립트는 먼저 젤리빈이 활성 상태인지 확인합니다. 그렇다면 충돌하는 객체가 플레이어인지 확인합니다. 그렇다면 스크립트는 다음을 수행합니다:

    • 오디오 플레이어에서 2D 오디오 트랙을 재생합니다.
    • 젤리빈을 보이지 않게 만듭니다.
    • 플레이어가 보이지 않는 젤리빈과 상호작용할 수 없도록 젤리빈을 비활성화합니다.
    • 젤리빈에 닿은 플레이어의 리더보드를 업데이트합니다.

    마지막으로, 스크립트는 각 젤리빈에 대해 Touched 이벤트에 함수를 연결하여 플레이어가 젤리빈에 닿을 때 onGumdropTouched 함수를 호출하도록 이벤트 리스너를 설정합니다.

  6. 게임을 플레이 테스트하여 젤리빈을 수집한 후 씹는 소리를 들으세요.

UI 상호작용

플레이어가 체크박스를 가리키거나 구매 버튼을 선택하는 등 사용자 인터페이스(UI) 요소와 상호작용할 때, 그들이 UI와 어떻게 상호작용하고 있는지를 직관적으로 이해할 수 있도록 즉각적인 피드백을 제공하는 것이 중요합니다. 예를 들어, 많은 디자이너는 플레이어가 설정을 활성화하거나 비활성화할 때 UI의 시각적 특성을 변경하여 설정의 상태를 전달합니다.

그러나 색상 변화나 애니메이션을 스스로 해석하기 어려운 시각 장애가 있는 플레이어의 경우, UI 상호작용에 대해 여러 형태의 감각 피드백을 제공하는 것이 유용하여 가능한 많은 플레이어가 접근할 수 있고 직관적으로 이해할 수 있도록 합니다. 이 개념을 확장하기 위해, UGC Homestore 템플릿의 구매 버튼에 중요한 다음 UI 상태를 고려해 보겠습니다:

  • 포커스 상태 - 플레이어가 선택할 준비를 하며 UI 요소를 강조하고 있음을 나타냅니다.
  • 호버 상태 - 플레이어가 커서로 UI 요소 위에 마우스를 올리고 있음을 나타냅니다.
  • 선택됨 - 플레이어가 입력을 통해 UI 요소를 선택했음을 나타냅니다.

이 세 가지 상호작용은 플레이어가 아바타 의상과 액세서리를 탐색하고 선택하며 구매하는 템플릿의 주요 사용자 흐름에 필수적이므로, 누구도 UI와 상호작용하는 방법에 대해 혼란스러워하지 않도록 하는 것이 가장 중요합니다. 플레이어의 성공을 위해, 템플릿은 각 UI 상호작용에 대해 시각적 및 청각적 피드백을 제공합니다.

시각적 피드백
기본 보기
포커스 상태
호버 상태
선택된 상태

여러 형태의 감각 피드백을 구성하는 방법의 예로, 샘플은 플레이어가 화면의 페퍼민트 버튼을 누를 때마다 시각적 및 청각적 피드백을 제공합니다. 플레이어가 버튼과 상호작용하지 않을 때, 버튼은 일반적인 페퍼민트 사탕처럼 보이지만, 버튼을 누르면 샘플은:

  • 즐거운 징글 오디오 트랙을 재생합니다.
  • 버튼에 청록색 음영을 추가합니다.
  • 버튼을 화면에서 약간 아래로 이동시킵니다.

여기서 이 상호작용을 메뉴 열기 또는 아이템 구매와 같은 유용한 게임 플레이 행동에 연결할 수 있습니다.

기본 보기
누른 상태

샘플 Gingerbread House - Complete Audio 장소 파일에서 원샷 UI 상호작용 오디오를 재현하려면:

  1. Explorer 창에서 StarterGui2DAudioButton으로 이동한 후:

    1. 오디오 소스를 생성하기 위해 AudioPlayer 객체를 삽입합니다.
    2. 게임 전반에 걸쳐 재생되는 스피커를 생성하기 위해 AudioDeviceOutput 객체를 삽입합니다.
    3. 오디오 플레이어에서 스피커로 스트림을 전달하기 위해 Wire 객체를 삽입합니다.
  2. AudioPlayer를 선택한 후, Properties 창에서 AssetIDrbxassetid://3422389728로 설정하여 레트로 징글 오디오 트랙을 재생합니다.

  3. Wire를 선택한 후, Properties 창에서,

    1. SourceInstance를 새 AudioPlayer로 설정하여 이 특정 오디오 플레이어에서 오디오를 전달하도록 지정합니다.
    2. TargetInstance를 새 AudioDeviceOutput으로 설정하여 이 특정 스피커로 오디오를 전달하도록 지정합니다.
  4. Explorer 창으로 돌아가 2DAudioButtonLocalScript를 삽입하고, 이름을 PlayAudioWhenPressed로 변경한 후, 다음 코드를 스크립트에 붙여넣습니다:

    local TweenService = game:GetService("TweenService")
    local buttonGui = script.Parent
    local buttonImageButton = buttonGui.ButtonFrame.ButtonImageButton
    local buttonAudioPlayer = buttonGui.AudioPlayer
    local tweenInfo = TweenInfo.new(.2, Enum.EasingStyle.Exponential)
    local buttonTweenByIsPressed = {
    -- 눌림
    [true] = TweenService:Create(buttonImageButton, tweenInfo, {
    Position = buttonImageButton.Position + UDim2.fromScale(0, .1),
    ImageColor3 = Color3.fromRGB(117, 255, 255),
    }),
    -- 기본
    [false] = TweenService:Create(buttonImageButton, tweenInfo, {
    Position = buttonImageButton.Position,
    ImageColor3 = Color3.fromRGB(255, 255, 255),
    }),
    }
    local function onIsPlayingChanged()
    local isPlaying = buttonAudioPlayer.IsPlaying
    local tween = buttonTweenByIsPressed[isPlaying]
    tween:Play()
    end
    onIsPlayingChanged()
    buttonAudioPlayer:GetPropertyChangedSignal("IsPlaying"):Connect(onIsPlayingChanged)
    buttonAudioPlayer.Ended:Connect(onIsPlayingChanged)
    buttonImageButton.Activated:Connect(function(_hit)
    buttonAudioPlayer:Play()
    end)

    이 스크립트는 다음을 가져옵니다:

    • UI 요소를 애니메이션화할 수 있도록 TweenService를 가져옵니다.
    • 스크립트의 부모인 2DAudioButton ScreenGui 객체를 가져옵니다.
    • 페퍼민트 사탕 ImageButton을 가져옵니다.
    • 관련 오디오 플레이어와 징글 오디오 트랙을 가져옵니다.

    그런 다음 스크립트는 다음을 정의합니다:

    • 버튼 애니메이션이 지수 애니메이션 스타일로 재생될 것임을 지정하는 TweenInfo 객체.
    • 버튼의 눌림 또는 눌리지 않음 상태를 나타내는 두 개의 트윈.
      • true 눌림 상태는 버튼을 화면에서 약간 아래로 이동시키고 청록색 음영을 추가합니다.
      • false 눌리지 않음 상태는 버튼을 화면의 원래 위치로 되돌리고 이전 음영을 제거합니다.

    스크립트의 나머지 부분은 UI 상호작용 피드백을 트리거하는 작업의 대부분이 발생하는 곳이므로, onIsPlayingChanged 함수와 이벤트 리스너가 UI 사용자 흐름을 위해 어떻게 함께 작동하는지 살펴보겠습니다:

    1. buttonImageButton.Activated는 플레이어가 버튼을 클릭하는 것을 감지하고, 오디오 플레이어에서 관련 오디오를 재생하기 위해 Play() 함수를 호출합니다. 이 과정에서 AudioPlayer.IsPlaying 속성이 false에서 true로 전환됩니다.
    2. buttonAudioPlayer:GetPropertyChangedSignal("IsPlaying")는 오디오 플레이어의 IsPlaying 속성이 변경되는 것을 감지하고, onIsPlayingChanged 함수를 호출합니다.
    3. onIsPlayingChanged 함수는 이 정보를 사용하여 화면에서 시각적 외관을 변경하는 트윈을 트리거합니다.
    4. 플레이어가 버튼을 빠르게 클릭하여 오디오를 우연히 다시 시작하지 않도록 하기 위해, buttonAudioPlayer.Ended는 오디오 플레이어가 재생을 마칠 때까지 기다린 후 다시 onIsPlayingChanged 함수를 호출합니다.

    onIsPlayingChanged 이벤트는 false에서 true로 변경될 때만 발생하므로, true에서 false로 변경될 때는 발생하지 않는다는 점에 유의해야 합니다. 이는 서버에서 클라이언트로 속성을 복제하는 타이밍 문제로 인한 의도된 동작입니다. 따라서 이 예제에서는 두 경우를 모두 처리하기 위해 Ended 이벤트가 제공되고 감지됩니다.

  5. 게임을 플레이 테스트하여 화면 버튼을 누를 때마다 징글 소리를 들으세요.

©2026 Roblox Corporation. Roblox 및 Roblox 로고, 'Powering Imagination'은 미국 및 기타 국가 내 당사의 등록 및 미등록 상표입니다.