2Dオーディオの追加

*このコンテンツは、ベータ版のAI(人工知能)を使用して翻訳されており、エラーが含まれている可能性があります。このページを英語で表示するには、 こちら をクリックしてください。

2Dオーディオは、特定の場所から発信されない非方向性の音であり、リスナーの位置や3D空間での向きに関係なく同じ音が再生されます。これは、プレイヤーが環境内でリスナーを移動させると、どこを向いても一貫して2Dオーディオを聞くことができることを意味します。

Gingerbread House - Start .rbxlファイルを出発点として、Gingerbread House - Complete Audioを参照しながら、このチュートリアルでは、ループする2Dオーディオとワンショットの2Dオーディオをゲームに追加する方法を示します。以下のガイダンスが含まれています:

  • プレイヤーがサーバーに接続するとすぐに再生されるループするバックグラウンドミュージック。
  • プレイヤーのゲームプレイ目標に応じて瞬時にフィードバックを提供するためのオーディオトリガー。
  • ユーザーインターフェースのさまざまなインタラクションを示すための音のアクティベーション。

プロセスのどの時点でも行き詰まった場合は、Gingerbread House - Complete Audioを参照して進捗を比較できます。

2Dオーディオオブジェクト

非方向性オーディオを作成するには、このチュートリアルで使用するオーディオオブジェクトを理解することが重要です。2Dオーディオには主に3つのタイプのオーディオオブジェクトがあります:

  • AudioPlayerオブジェクトは、オーディオファイルをロードして再生します。
  • AudioDeviceOutputオブジェクトは、スピーカーやヘッドフォンなどの物理ハードウェアデバイスです。
  • Wiresは、オーディオストリームを1つのオブジェクトから別のオブジェクトに運びます。

これらのオーディオオブジェクトはすべて、ファイル再生から各プレイヤーのハードウェアに音を運ぶために連携して機能します。プレイヤーがヘッドセットを装着してノートパソコンでゲームをプレイしている例を使って、これがどのように機能するか見てみましょう:

  • AudioPlayerは、通貨購入音のために127645268874265オーディオアセットIDをゲームにロードします。
  • Wireは、AudioPlayerからAudioDeviceOutputにストリームを運び、プレイヤーのヘッドセットから音が出るようにします。
  • AudioDeviceOutputオブジェクトは、音をプレイヤーの物理スピーカー、またはこの場合はヘッドフォンに運びます。

以下のセクションでは、これらのオブジェクトをより深く掘り下げ、ループする2Dオーディオとワンショットの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に変更し、RunContextプロパティをClientに設定し、次のコードをスクリプトに貼り付けます:

    local audioPlayer = script.Parent
    audioPlayer:Play()

    スクリプトは、スクリプトの親AudioPlayerを表す変数を宣言することから始まります。次に、スクリプトはプレイヤーがゲームに参加した瞬間からゲームを終了する瞬間までオーディオソースを再生するように設定します。

  6. ゲームをプレイテストして、ループするバックグラウンドミュージックを聞きます。

ワンショットオーディオ

ワンショット2Dオーディオ、または特定の時間と位置で一度再生される非方向性オーディオは、プレイヤーが見逃してほしくないことについて重要なコンテキストを提供します。このタイプの聴覚フィードバックをゲームに使用することは、ボス戦の開始や大きな健康の喪失など、重要なゲームプレイ機能やプレイヤーアクションに対して即座に明確な応答を提供するために不可欠です。

以下のセクションでは、プレイヤーがタイムリーで非方向性のフィードバックを必要とする一般的なゲームプレイシナリオの実装詳細を提供します。これには、ゲームプレイフィードバック、UI要素のインタラクション、およびチュートリアルの音声ナレーションが含まれます。

ゲームプレイフィードバック

プレイヤーがゲームを進めるにつれて、スコア、健康、レベルの進行状況など、ゲームプレイに影響を与えるものの状態について即座に聴覚的フィードバックを受け取ることが重要です。このタイプのオーディオはプレイヤーの目標に直接関連しているため、これらの音は明確で聞こえやすく、有用で正確な情報を伝えることが重要です。

この概念を示すために、プレイヤーがジャンプしてコインを集めるときに再生されるPlatformerテンプレートからの以下のワンショット2Dオーディオを確認しましょう:

  • プレイヤーがデバイスのジャンプキーを押すと、空気のようなウィーンという音が再生されます。
  • プレイヤーのキャラクターがコインに触れると、高音のディングとコインが揺れる音が再生されます。

これらの音は3D空間の文脈内で瞬時に認識でき、プレイヤーが視覚的な手がかりだけに頼ることなく、自分の行動の成功を理解するのに役立ちます。

複数の音を同時に再生するとき、特定の音はプレイヤーが聞くべき重要度が高い場合があります。この場合、コイン収集音はジャンプ音よりも価値のあるゲームプレイ情報を伝えているため、ゲームはそれをわずかに高い音量で再生します。ただし、素晴らしいミックスを達成するための基準やルールはないため、ゲーム内の音を調整して、最も重要だと感じるものを反映させてください。

たとえば、サンプルにはゲーム全体でさまざまなオーディオトリガーが含まれていますが、それらはすべてゲームの主な目的を理解するための重要度が同じではありません:ガムドロップを集めてジンジャーブレッドハウスを開くことです。プレイヤーが何をすべきかを認識できるようにするために、サンプルはプレイヤーがガムドロップを収集するたびに聴覚フィードバックの振幅を3倍にします。

サンプルの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を3つになるまで複製し、環境内に散らばせます。

  5. 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.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)
    -- プレイヤーが3つのガムドロップを収集したか確認
    if newGumdropAmount >= 3 then
    -- プレイヤーが3つのガムドロップを収集したときにドアイベントオーディオを再生
    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

    このスクリプトは、WorkspacePlayersServerStorage、およびTweenServiceサービスを初期化して、子要素と機能を参照できるようにします。次に、LeaderboardPlayerDataモジュールをServerStorageから要求します。これらのモジュールは、環境内でプレイヤーが収集するガムボールの量を追跡するために、画面の右上隅にリーダーボードを作成および更新する役割を担っています。

    スクリプトのupdatePlayerGumdrops関数は、プレイヤーがガムドロップを収集するたびにリーダーボードを更新し、3つのガムドロップを収集した瞬間を待って、ジンジャーブレッドハウスのドアのための位置音とアニメーションをトリガーする役割を担っています。このスクリプトのこの部分についての詳細は、Add 3D audio - Event feedbackを参照してください。

    スクリプトのonGumdropTouched関数は、ゲームプレイフィードバックのための2Dオーディオをトリガーするための作業の大部分が行われる場所で、2つの引数を取ります:

    • otherPart - ガムドロップと衝突するパート。
    • gumdrop - ガムドロップを表す球状のパート。

    何かがガムドロップパートと衝突すると、スクリプトはまずガムドロップがアクティブかどうかを確認します。そうであれば、衝突しているオブジェクトがプレイヤーであることを確認します。そうであれば、スクリプトは次のことを行います:

    • オーディオプレーヤーから2Dオーディオトラックを再生します。
    • ガムドロップを見えなくします。
    • プレイヤーが見えないガムドロップとインタラクトできないようにガムドロップを非アクティブにします。
    • ガムドロップに触れたプレイヤーのためにリーダーボードを更新します。

    最後に、スクリプトはイベントリスナーを設定し、各ガムドロップに対して、Touchedイベントに関数を接続し、プレイヤーがガムドロップに触れたときにonGumdropTouched関数を呼び出します。

  6. ゲームをプレイテストして、ガムドロップを収集した後に噛む音を聞きます。

UIインタラクション

プレイヤーがチェックボックスにカーソルを合わせたり、購入ボタンを選択したりするなど、ユーザーインターフェース(UI)要素とインタラクトする際には、即座にフィードバックを提供することが重要です。これにより、プレイヤーは自分がUIとどのようにインタラクトしているかを直感的に理解できます。たとえば、多くのデザイナーは、プレイヤーが設定を有効または無効にするときにUIの視覚的特性を変更して、設定の状態を伝えます。

ただし、色の変化やアニメーションが自分で解読するのが難しい視覚障害のあるプレイヤーにとっては、UIインタラクションのために複数の感覚フィードバックを提供することが役立ちます。これにより、できるだけ多くのプレイヤーにとってアクセス可能で直感的なものになります。この概念を拡張するために、UGC Homestoreテンプレートの購入ボタンにとって重要な以下のUI状態を考えてみましょう:

  • フォーカス中 - プレイヤーが選択する準備をしているUI要素をハイライトしていることを示します。
  • ホバー中 - プレイヤーがカーソルでUI要素の上にホバーしていることを示します。
  • 選択済み - プレイヤーが入力を通じてUI要素を選択したことを示します。

これらの3つのインタラクションは、プレイヤーがアバターの衣服やアクセサリーをブラウズ、選択、購入するというテンプレートの主要なユーザーフローにとって不可欠であるため、誰もが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オブジェクト。
    • ボタンの押された状態または未押された状態を表す2つのツイーン。
      • trueの押された状態は、ボタンを画面上でわずかに下に移動させ、ティール色に染めます。
      • falseの未押された状態は、ボタンを画面上の元の位置に戻し、前の色を取り除きます。

    スクリプトの残りの部分は、2D 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に変更されたときのみ発火することに注意してください。これは、サーバーからクライアントへのプロパティの複製のタイミングに関する問題のため、意図された動作です。このため、両方のケースをカバーするために、Endedイベントが提供され、リスニングされています。

  5. ゲームをプレイテストして、画面上のボタンを押すたびにジングルを聞きます。

©2026 Roblox Corporation。Roblox(ロブロックス)、RobloxロゴおよびPowering Imaginationは、米国並びにその他の国における登録商標および非登録商標です。