3Dオーディオの追加

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

3Dオーディオは、3D空間の特定の位置から発生する方向性のある音であり、オーディオエミッターとリスナーの間の距離と向きに応じて音量が増減します。つまり、リスナーやエミッターが環境内を移動するにつれて、プレイヤーは異なる方向や音量レベルからその音を動的に聞くことができます。

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

  • プレイヤーがサーバーに接続するとすぐに再生されるループする環境音。
  • プレイヤーのゲームプレイにとって重要な重要な状況イベントについて知らせるためのオーディオのトリガー。
  • 3Dオブジェクトと対話する際にプレイヤーに聴覚的フィードバックを提供するためのオーディオのアクティベーション。
  • 環境内の興味のあるポイントにプレイヤーを引き付け、導くキャラクターのサウンドバイトを再生します。

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

オーディオオブジェクト

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

  • AudioPlayerオブジェクトは、オーディオファイルをロードして再生します。
  • AudioEmitterオブジェクトは、3D環境にオーディオを発信する仮想スピーカーです。
  • AudioListenerオブジェクトは、3D環境からオーディオを拾う仮想マイクです。
  • AudioDeviceOutputオブジェクトは、スピーカーやヘッドフォンなどの現実世界の物理ハードウェアデバイスです。
  • AudioDeviceInputオブジェクトは、現実世界の物理マイクです。
  • Wiresは、オーディオストリームを1つのオブジェクトから別のオブジェクトに運びます。

これらのオーディオオブジェクトはすべて、実世界の対応物と同様に音を発生させるために連携して機能します。プレイヤーがヘッドセットを装着してラップトップでゲームをプレイしている例を使って、これがどのように機能するかを見てみましょう:

  • AudioPlayerは、雨のトラック用の1516791621オーディオアセットIDをゲームにロードします。
  • AudioEmitterは、3D環境に雨のトラックオーディオのストリームを発信します。
  • Wireは、ストリームが3Dスピーカーから出るように、AudioPlayerからAudioEmitterにストリームを運びます。
  • キャラクターの子であるAudioListenerオブジェクトは、その音を3D環境内で聞き取り、ヘッドセットにフィードバックします。
  • AudioDeviceOutputオブジェクトは、AudioListenerからプレイヤーの物理スピーカー、またはこの場合はヘッドフォンに音を運びます。
  • AudioDeviceInputオブジェクトは、現実世界から音をキャプチャし、ボイスチャット用にゲームにフィードバックします。
ゲーム内のオブジェクトの表現
現実世界のオブジェクトの表現

以下のセクションでは、これらのオブジェクトをより深く掘り下げ、ループする3Dオーディオとワンショットの3Dオーディオを再生する方法を学びます。これらのオブジェクトを今後の技術と共にレビューすることで、ゲームからプレイヤーへの音のキャプチャとフィードバックをより正確に予測できるようになります。

ループオーディオ

ループする3Dオーディオ、またはプレイヤーがサーバーに接続するとすぐにシームレスに繰り返される方向性のあるオーディオは、3D空間の雰囲気を高めるための一般的なサウンドデザイン技術です。これにより、環境音源が一貫性を保ち、テレビの静電気や滝の轟音などが再現されます。これらの音が突然止まると、環境は非現実的に感じられます。

この概念を示すために、次の2つの大きな滝のための3Dオーディオが、ループしていないオーディオトラックが完了するとすぐに停止する様子を確認してください。水の音は最初にプレイヤーを屋外環境に没入させますが、突然の音の変化は、現実世界の滝の動作に対して不自然で衝撃的です。

同様に、サンプルでは流れるチョコレートの滝のためにこの技術を使用し、プレイヤーのオーディオエミッターからの距離に応じて音量を調整します。プレイヤーが20スタッド未満の距離にいるとき、エミッターは音をフルボリュームで発信します。プレイヤーがさらに離れると、スロッシングオーディオはオーディオエミッターから20スタッドごとに音量が減少します。これは、現実世界の音がソースから遠ざかるにつれて音量が減少することを模倣しています。

サンプルのGingerbread House - Complete Audioプレースファイルでループする3Dオーディオを再現するには:

  1. プレイヤーキャラクターに接続されたデフォルトリスナーを有効にします。

    1. Explorerウィンドウで、SoundServiceを選択します。
    2. Propertiesウィンドウで、DefaultListenerLocationCharacterに設定します。ゲームを実行すると、エンジンは自動的に:
      • 各プレイヤーキャラクターのHumanoid.RootPartの下にAudioListenerを作成し、ゲーム内の音源の位置とスケールに応じて現実世界のスピーカーで音がシフトするのを聞くことができます。
      • SoundServiceの下にAudioDeviceOutputを作成します。
  2. Explorerウィンドウで、WorkspaceWaterfallAudioObjectに移動し、次に:

    1. 滝のオーディオソースを作成するためにAudioPlayerオブジェクトを挿入します。
    2. WaterfallAudioObjectから位置ストリームを発信するためにAudioEmitterオブジェクトを挿入します。
    3. オーディオプレイヤーからオーディオエミッターへのストリームを運ぶためにWireオブジェクトを挿入します。
  3. AudioPlayerを選択し、Propertiesウィンドウで、

    1. AssetIDrbxassetid://1516791621に設定して、雨のオーディオトラックを再生します。
    2. Loopingを有効にして、オーディオがシームレスに繰り返されるようにします。
  4. AudioEmitterを選択し、Propertiesウィンドウで、DistanceAttenuation{0: 1}, {20: 0.8}, {40: 0.4}, {80: 0}に設定して、音がオーディオエミッターから20スタッドごとに音量が徐々に減少するようにします。

  5. Wireを選択し、Propertiesウィンドウで、

    1. SourceInstanceを新しいAudioPlayerに設定して、この特定のオーディオプレイヤーからオーディオを運ぶように指定します。
    2. TargetInstanceを新しいAudioEmitterに設定して、この特定のオーディオエミッターにオーディオを運ぶように指定します。
  6. Explorerウィンドウに戻り、WaterfallAudioObjectScriptを挿入し、名前をLoopWaterfallMusicに変更し、RunContextプロパティをClientに設定し、次のコードをスクリプトに貼り付けます:

    local audioPlayer = script.Parent
    audioPlayer:Play()

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

  7. ゲームをプレイテストして、アバターが滝の近くにいるときにループするチョコレート雨の音を聞きます。キャラクターの頭を回転させて別の方向を見ると、音は3D空間内のエミッターの位置に応じて現実世界のスピーカーで動的にシフトします。

ワンショットオーディオ

ワンショット3Dオーディオ、または特定の時間と位置で一度再生される方向性のあるオーディオは、プレイヤーに自分の行動、環境、および周囲のキャラクターについてのコンテキストを提供します。このタイプの聴覚フィードバックをゲームに使用することは重要です。なぜなら、プレイヤーが敵を避けたり、役立つアイテムを拾ったりするなどの戦略的な決定を下すことを可能にするからです。

以下のセクションでは、プレイヤーがタイムリーで方向性のあるフィードバックを必要とする一般的なゲームプレイシナリオの実装詳細を提供します。これには、状況に応じたゲームプレイイベント、オブジェクトのインタラクション、および非プレイ可能キャラクターのダイアログが含まれます。

イベントフィードバック

プレイヤーが新しいゲームプレイエリアをアンロックしたり、敵の攻撃を促したりするなど、環境内で重要な状況イベントをトリガーするとき、彼らが3D空間内でどこに焦点を合わせるべきかを理解することが重要です。即座の聴覚フィードバックがないと、プレイヤーはゲームプレイにとって重要な情報を見逃し、次にどこに行くべきか、何をすべきかがわからずにフラストレーションを感じる可能性があります。

これがなぜ重要であるかを示すために、Laser Tagテンプレートからのワンショット3Dオーディオを確認しましょう。これは各プレイヤーのブラスターから再生されます:

  • プレイヤーがブラスターから発射するたびに深いポップ音が再生されます。
  • プレイヤーが新しい弾薬でブラスターをリロードするたびに、クリック音とロボットのビープ音が再生されます。

これらの音は、すべての近くのプレイヤーに発射音の方向を知らせることで状況認識を提供し、彼らが楽しみに参加するか、潜在的な危険を避けるかの情報に基づいた決定を下すことができるようにします。

サンプルでは、この技術を使用して、ゲーム内の主要な目的を達成した際の報酬についてプレイヤーに状況認識を提供します。プレイヤーが3つのガムドロップをすべて集めると、ジンジャーブレッドハウスのドアが開き、内部のプレゼントにアクセスできるようになります。

プレイヤーがガムドロップを集める必要がある特定の順序がないため、どのガムドロップを最後に集めても、プレイヤーがドアが開くことを認識することが重要です。位置音はこれを可能にし、プレイヤーが成功を認識し、次にどこに行くべきかを知ることができるようにします。

サンプルのGingerbread House - Complete Audioプレースファイルでワンショットイベントフィードバック3Dオーディオを再現するには:

  1. Explorerウィンドウで、WorkspaceDoorに移動し、次に:

    1. ボリュームのオーディオソースを作成するためにAudioPlayerオブジェクトを挿入します。
    2. Doorから位置ストリームを発信するためにAudioEmitterオブジェクトを挿入します。
    3. オーディオプレイヤーからオーディオエミッターへのストリームを運ぶためにWireオブジェクトを挿入します。
  2. AudioPlayerを選択し、Propertiesウィンドウで、AssetIDrbxassetid://5930776613に設定して、スライディングメタルゲートのオーディオトラックを再生します。

  3. Wireを選択し、Propertiesウィンドウで、

    1. SourceInstanceを新しいAudioPlayerに設定して、この特定のオーディオプレイヤーからオーディオを運ぶように指定します。
    2. TargetInstanceを新しいAudioEmitterに設定して、この特定のオーディオエミッターにオーディオを運ぶように指定します。
  4. 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("Enabled") then
    local character = otherPart.Parent
    local player = Players:GetPlayerFromCharacter(character)
    if player then
    -- プレイヤーがガムドロップに触れた
    local audioPlayer = gumdrop.AudioPlayer
    audioPlayer:Play()
    gumdrop.Transparency = 1
    gumdrop:SetAttribute("Enabled", false)
    updatePlayerGumdrops(player, function(oldGumdropAmount)
    oldGumdropAmount = oldGumdropAmount or 0
    return oldGumdropAmount + GUMDROP_AMOUNT_TO_ADD
    end)
    print("プレイヤーがガムドロップを集めました")
    end
    end
    end
    -- イベントリスナーの設定
    for _, gumdrop in gumdrops do
    gumdrop:SetAttribute("Enabled", true)
    gumdrop.Touched:Connect(function(otherPart)
    onGumdropTouched(otherPart, gumdrop)
    end)
    end

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

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

    • player - ガムドロップを集めるプレイヤー。
    • updateFunction - プレイヤーの集めたガムドロップの数を更新するコールバック関数。

    プレイヤーがガムドロップに衝突すると、スクリプトは:

    • PlayerData.updateValue関数を呼び出して、プレイヤーの新しいガムドロップ収集量の値を取得します。
    • Leaderboard.setStat関数を呼び出して、この新しい量でリーダーボードを更新します。
    • その量が3以上であるかどうかを確認します。

    この値が3以上になると、スクリプトは:

    • オーディオプレイヤーからオーディオエミッターに3Dオーディオトラックを再生します。
    • ドアを現在の位置から線形に15スタッド下に移動させます。

    スクリプトの残りの部分は、ガムドロップに衝突するものがプレイヤーであるかどうかを検出し、収集フィードバックのために非位置音をトリガーする役割を担っています。このスクリプトのこの部分に関する詳細については、Add 2D audio - Gameplay feedbackを参照してください。

  5. ゲームをプレイテストして、環境内の3つのガムドロップをすべて集めた後にスライドゲートの音を聞きます。カメラを回転させると、音は3D空間内のエミッターの位置に応じて現実世界のスピーカーで動的にシフトします。

オブジェクトインタラクション

プレイヤーが環境内の3Dオブジェクトと対話する際、たとえばライトスイッチをオンにしたり武器を拾ったりする場合、即座のフィードバックを提供することが重要です。これにより、プレイヤーはオブジェクトとのインタラクションの方法を直感的に理解できます。視覚的および聴覚的フィードバックの組み合わせは、プレイヤーの行動と環境の反応との因果関係を強化します。

この概念を拡張するために、Plantサンプルからの次のワンショット3Dオーディオを確認し、キャベツを育てるユーザーフローを見てみましょう:

  • プレイヤーが種を植えるときに優しいクリンク音が再生されます。
  • プレイヤーが成長中の植物に水をやるときに湿ったスプラッシュ音が再生されます。
  • プレイヤーが成長した植物を収穫するときにクリップ音が再生されます。
  • プレイヤーがキャベツをワゴンに置くときに柔らかい音が再生されます。

これらの音はすべて、3D空間内で形を変えるオブジェクトとのプレイヤーの近接プロンプトの主要なインタラクションを強化します。視覚障害のあるプレイヤーにとって、色の変化やアニメーションが自分で解読するのが難しい場合、これらの複数の感覚フィードバックを提供することで、3Dオブジェクトのインタラクションをできるだけ多くのプレイヤーにとってアクセス可能で直感的に保つことができます。

オブジェクトインタラクションに複数の感覚フィードバックの形式を構成する方法の別の例を示すために、サンプルではプレイヤーがジンジャーブレッドハウス内の3Dペパーミントボタンを踏むたびに視覚的および聴覚的フィードバックを提供します。プレイヤーがボタンと対話していないとき、ボタンは通常のペパーミントキャンディのように見えますが、ボタンを踏むと、サンプルは:

  • お祝いのジングルオーディオトラックを再生します。
  • ボタンの側面を緑色に染めます。
  • ボタンを地面に移動させます。

ここから、このインタラクションをアイテムのロック解除や特別な能力のトリガーなど、さまざまなユニークなゲームプレイアクションに接続できます。

デフォルトビュー
押された状態

サンプルのGingerbread House - Complete Audioプレースファイルでワンショットオブジェクトインタラクション3Dオーディオを再現するには:

  1. Explorerウィンドウで、Workspace3DAudioButtonに移動し、次に:

    1. ボタンのオーディオソースを作成するためにAudioPlayerオブジェクトを挿入します。
    2. 3DAudioButtonから位置ストリームを発信するためにAudioEmitterオブジェクトを挿入します。
    3. オーディオプレイヤーからオーディオエミッターへのストリームを運ぶためにWireオブジェクトを挿入します。
  2. AudioPlayerを選択し、Propertiesウィンドウで、AssetIDrbxassetid://1846248593に設定して、陽気でお祝いのオーディオトラックを再生します。

  3. Wireを選択し、Propertiesウィンドウで、

    1. SourceInstanceを新しいAudioPlayerに設定して、この特定のオーディオプレイヤーからオーディオを運ぶように指定します。
    2. TargetInstanceを新しいAudioEmitterに設定して、この特定のオーディオエミッターにオーディオを運ぶように指定します。
  4. Explorerウィンドウに戻り、3DAudioButtonScriptを挿入し、名前をPlayAudioWhenPressedに変更し、次のコードをスクリプトに貼り付けます:

    local TweenService = game:GetService("TweenService")
    local buttonModel = script.Parent.Parent
    local buttonPart = buttonModel.ButtonPart
    local buttonPressedAudioPlayer = buttonModel.ButtonPressedAudioPlayer
    local 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.IsPlaying
    local tween = buttonTweenByIsPressed[isPlaying]
    tween:Play()
    end
    onIsPlayingChanged()
    buttonPressedAudioPlayer:GetPropertyChangedSignal("IsPlaying"):Connect(onIsPlayingChanged)
    buttonPressedAudioPlayer.Ended:Connect(onIsPlayingChanged)
    buttonPart.Touched:Connect(function(_hit)
    buttonPressedAudioPlayer:Play()
    end)

    スクリプトは、次のものを取得することから始まります:

    • 地面から突き出たボタンのパートをアニメーションさせるためにTweenService
    • スクリプトの親である3DAudioButtonモデル。
    • 地面から突き出たボタンのパート。
    • お祝いの音オーディオトラックを持つ関連オーディオプレイヤー。

    スクリプトは次に、次のものを定義します:

    • ボタンのアニメーションが指数関数的なアニメーションスタイルで再生されることを指定するTweenInfoオブジェクト。
    • ボタンの押された状態または未押された状態を表す2つのツイーン。
      • trueの押された状態は、ボタンをわずかに地面に押し込み、パートの側面を緑色に染めます。
      • falseの未押された状態は、ボタンを元の位置に戻し、前の色を取り除きます。

    スクリプトの残りの部分は、オブジェクトインタラクションフィードバックのための作業の大部分が行われる場所です。onIsPlayingChanged関数とイベントリスナーがどのように連携して機能するかを確認しましょう:

    1. buttonPart.Touchedは、プレイヤーがボタンに触れるのを待ち、関連するオーディオプレイヤーからオーディオを再生するためにPlay()関数を呼び出します。このプロセスは、AudioPlayer.IsPlayingプロパティをfalseからtrueに切り替えます。
    2. buttonPressedAudioPlayer:GetPropertyChangedSignal("IsPlaying")は、オーディオプレイヤーのIsPlayingプロパティが変更されるのを待ち、onIsPlayingChanged関数を呼び出します。
    3. onIsPlayingChanged関数は、この情報を使用して3D空間内の視覚的外観を変更するツイーンをトリガーします。
    4. プレイヤーがボタンに素早くジャンプして触れた場合にオーディオが誤って再起動されないように、buttonPressedAudioPlayer.Endedはオーディオプレイヤーが再生を終了するのを待ち、再度onIsPlayingChanged関数を呼び出します。

    onIsPlayingChangedイベントは、falseからtrueに変わったときのみ発火することに注意してください。これは、サーバーからクライアントへのプロパティの複製のタイミングに関する問題があるため、意図された動作です。このため、両方のケースをカバーするために、Endedイベントが提供され、リスニングされています。

  5. ゲームをプレイテストして、プレイヤーキャラクターがジンジャーブレッドハウスの3Dボタンに触れたときにお祝いの音を聞きます。ボタンから離れると、音の音量が減少します。

キャラクターダイアログ

非プレイ可能キャラクター(NPC)からの方向性のあるオーディオを提供することは、プレイヤーを環境内の興味のあるポイントに導くのに役立ち、他のキャラクターとのインタラクションに深みを加えます。実際、物語主導のゲームでは、多くのデザイナーがキャラクターダイアログを戦略的に使用して、プレイヤーにキャラクター、味方や敵のキャラクター、または世界自体について間接的に教えます。

この技術の一般的な例には、次のようなものがあります:

  • ダイアログスタイルでゲームのトーンを設定します。
  • バンターでキャラクターの関係についてプレイヤーに教えます。
  • 敵の会話で動機やプレイヤーに対する位置を告白します。
  • プレイヤーキャラクターが自分の考えを声に出して話すことで、プレイヤーが次に何をすべきかを優しく導きます。たとえば、自分を癒す、別の場所に移動する、アイテムを見つけるなどです。
  • 味方キャラクターがプレイヤーキャラクターと話すことで、ゲーム内の世界の詳細、歴史、文化、社会問題を明らかにします。

これが実際にどのように見えるかを示すために、Beyond the Darkショーケースからの次のワンショット3Dオーディオを確認しましょう。これは、プレイヤーが宇宙ステーションのメインロビーエリアにいるときに定期的に再生されます。

宇宙ステーションをキャラクターとして使用することで、このダイアログクリップは、全体的な設定に関する重要なコンテキストと伝説をプレイヤーに提供します。たとえば、この一文からプレイヤーは次のことを学びます:

  • 彼らは宇宙におり、特にKerr-Newman Deep Space Relay 14という名前の宇宙ステーションにいます。
  • 彼らの環境は未来的で歓迎的です。
  • 彼らは訪問者であり、すぐに出発する可能性があります。

これらの詳細は、プレイヤーを環境に没入させ、彼らの任務に対する緊急感を加えます。しかし、プレイヤーが自分の主な任務が何であるかを知らない場合、キャラクターダイアログを使用して、ゲーム内で何をしてほしいかをプレイヤーに知らせることもできます。

サンプルでは、雪だるまからのキャラクターダイアログをトリガーするために、3D空間内のボリューム、または見えない領域を使用して、プレイヤーが3つのガムドロップを集めて彼の家のドアを開けるように導きます。プレイヤーがゲームに参加したときに最初に見るものの1つとして、プレイヤーはダイアログをトリガーし、成功するために何をすべきかを知る可能性が高くなります。

雪だるまの周りのボリュームは、プレイヤーが3D領域に入るとオーディオを再生するために衝突フィードバックを使用します。

サンプルのGingerbread House - Complete Audioプレースファイルでワンショットキャラクターダイアログ3Dオーディオを再現するには:

  1. Explorerウィンドウで、WorkspaceDialogueVolumeに移動し、次に:

    1. ボリュームのオーディオソースを作成するためにAudioPlayerオブジェクトを挿入します。
    2. DialogueVolumeから位置ストリームを発信するためにAudioEmitterオブジェクトを挿入します。
    3. オーディオプレイヤーからオーディオエミッターへのストリームを運ぶためにWireオブジェクトを挿入します。
  2. AudioPlayerを選択し、Propertiesウィンドウで、AssetIDrbxassetid://92917410841704に設定して、ゲームの目的に関する指示音を再生します。

  3. Wireを選択し、Propertiesウィンドウで、

    1. SourceInstanceを新しいAudioPlayerに設定して、この特定のオーディオプレイヤーからオーディオを運ぶように指定します。
    2. TargetInstanceを新しいAudioEmitterに設定して、この特定のオーディオエミッターにオーディオを運ぶように指定します。
  4. Explorerウィンドウに戻り、StarterPlayerStarterCharacterScriptsに移動し、LocalScriptを挿入し、名前をPlayAudioWhenInVolumeに変更し、次のコードをローカルスクリプトに貼り付けます:

    local Workspace = game:GetService("Workspace")
    local Players = game:GetService("Players")
    local humanoid = script.Parent:WaitForChild("Humanoid")
    local volumeDetector = Workspace.DialogueVolume
    local trigger = humanoid:WaitForChild("Animator")
    local debounce = false
    local localPlayer = Players.LocalPlayer
    volumeDetector.Touched:Connect(function(hit)
    if debounce then
    return
    end
    local hitCharacter = hit:FindFirstAncestorWhichIsA("Model")
    local hitPlayer = Players:GetPlayerFromCharacter(hitCharacter)
    if hitPlayer ~= localPlayer then
    return
    end
    debounce = true
    local audioPlayer = Workspace.DialogueVolume.AudioPlayer
    audioPlayer:Play()
    audioPlayer.Ended:Wait()
    debounce = false
    end)

    このスクリプトは、WorkspaceとPlayersサービスを取得して、子供や機能を参照できるようにします。各プレイヤーキャラクターがゲームにロードまたはリスポーンするたびに、スクリプトは次のものを待ちます:

    • キャラクターのHumanoidAnimatorオブジェクト。
    • ワークスペース内のDialogueVolumeという名前のボリュームオブジェクト。

    ボリュームに何かが衝突すると、Touchedイベントハンドラ関数は、ボリュームと衝突したBasePartがキャラクターモデルの子孫である場合、最初の祖先をModelとして取得します。もしそうであれば、関数は次のことを行います:

    • デバウンスをtrueに設定します。
    • オーディオを再生し、終了するのを待ちます。
    • デバウンスをfalseに戻します。

    デバウンスをfalseからtrueに、再生が終了した後に再びfalseに設定することは、プレイヤーがボリュームと継続的に衝突する際にオーディオが繰り返しトリガーされるのを防ぐためのデバウンスパターンです。デバウンスパターンの詳細については、Debounce - Detect collisionsを参照してください。

  5. ゲームをプレイテストして、プレイヤーキャラクターが雪だるまの周りのボリュームに触れたときに指示音を聞きます。

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