はじめに
ADXアンバサダーとして記事を書いておりますSigと申します。
この記事は、UE5のGameplayTagとADX for UEを組み合わせてサウンドを管理する実装の活用法です。
前回の「キャラクターごとのボイスをタグで管理する」記事では、キャラクタータグとアクションタグを組み合わせてボイスを再生する仕組みを作りました。
UE5 + ADXで、キャラクターごとのボイスをタグで管理する
(キャラタグ記事リンク)
しかしあの実装では、データテーブルに登録していないタグの組み合わせで呼び出すと、行が見つからずボイスが再生されないという問題がありました。
たとえば、近接職共通のスキルボイスはデータテーブルに登録しても、戦士固有のスキルボイスは用意していない場合、戦士がスキルを使っても何も鳴りません。
今回の記事では、その問題を解決する「親タグへのフォールバック」の仕組みを作ります。戦士固有のボイスがなければ、タグ階層をひとつ上にたどって、近接職共通のボイスを再生するという挙動です。
当記事ではUE5.7 及び 「ADX LE UE SDK(2.05.01)」を使用します。
また、基本的にブループリントのみでの実装を行います。
ADX for UEはインディー向けの「LE版」であれば、無料で使用できます。
前提
「ADX for UE LE」を使用します。導入や簡単な使い方は以下の記事にあります。
ADX for UEの導入で、一歩上のサウンド表現を(導入編)
ADX for UEの導入で、一歩上のサウンド表現を(実践編)
キャラタグ記事の実装を使用します。先にこちらを参照いただけると行程がイメージしやすいと思います。
UE5 + ADXで、キャラクターごとのボイスをタグで管理する
(記事リンク)
実装
現状の問題の確認
キャラタグ記事で作ったデータテーブルを振り返ります。
以下のように登録されていました。
- 「Character.Melee_Sound.Voice.Attack」→ CV_Melee_Attack(近接職共通)
- 「Character.Melee_Sound.Voice.Damaged」→ CV_Melee_Damaged(近接職共通)
- 「Character.Melee_Sound.Voice.Skill」→ CV_Melee_Skill(近接職共通)
- 「Character.Melee.Knight_Sound.Voice.Skill」→ CV_Melee_Knight_Skill(騎士固有)
騎士にはスキルボイスの固有キューがありますが、戦士にはありません。
現状の実装で戦士がスキルを使うと、「Character.Melee.Warrior_Sound.Voice.Skill」というキーでデータテーブルを検索しますが、該当する行がないためボイスが再生されません。
これを解決するために、「見つからなかったら親タグに遍って再検索する」フォールバック処理を追加します。
フォールバックの流れ
フォールバック処理の流れは以下のようになります。
- 戦士のスキル使用時ボイス → 「Character.Melee.Warrior_Sound.Voice.Skill」で検索
- 見つからない → キャラクタータグの親タグを取得(Character.Melee.Warrior → Character.Melee)
- 「Character.Melee_Sound.Voice.Skill」で再検索 → ヒット! → 近接職共通のスキルボイスを再生
- 見つからない → キャラクタータグの親タグを取得(Character.Melee.Warrior → Character.Melee)
もし近接職共通にも登録がなければ、さらに親タグへ遍ります。
- Character.Melee → Character
- 「Character_Sound.Voice.Skill」で再検索 → ヒットすればキャラクター全体共通のボイスを再生
- それでも見つからない → これ以上親タグがないので、再生しない
- 「Character_Sound.Voice.Skill」で再検索 → ヒットすればキャラクター全体共通のボイスを再生
この仕組みにより、データテーブルに固有の行があればそれを再生し、なければ自動的に共通のボイスを探して再生するという挙動になります。
親タグを取得する関数を作る
フォールバック処理の核となる「親タグの取得」を、文字列操作で実現します。
やりたいことはシンプルで、タグ名の最後の「.」から後ろを切り落として、ひとつ上の階層のタグ名を得ることです。
例: 「Character.Melee.Warrior」→ 最後の 「.」 から後ろを切る → 「Character.Melee」
関数ライブラリ「BFL_SoundUtility」を開き、新しい関数「GetParentTagName」を作成します。
Datailsパネルにて、引数と戻り値を設定します。
- 引数: TagName(Name型)… 解析したいタグの文字列
- 戻り値: ParentTagName(Name型)… 親タグの文字列
- 戻り値: bSuccess(Boolean型)… 親タグが取得できたかどうか
最後の「.」の位置を見つけるには?
まず引数のTagNameを文字列に変換します。Name型からString型への変換は自動的に行われる場合もありますが、明示的に変換する場合は (Name) To Stringノードを使用します。
文字列の中から最後の「.」を見つけるために、Find Substringノードを使用します。
- Search In: TagNameを変換した文字列
-
Substring:
.(ドット)1文字 - Search from End: Trueに設定
Search from End をTrueにすることで、末尾から逆方向に検索し、最後のドットの位置が取得できます。
このノードは見つかった位置を整数(0始まりのインデックス)で返します。見つからなかった場合は -1 が返ります。
-1 が返ったということは「もうドットがない = これ以上親タグがない」という意味になりますので、この値でフォールバックの終了を判断します。
Branchノードで結果が「-1」より大きいか(ドットが見つかったか)を判定します。
ドットより左側だけを取り出す
ドットが見つかったTrue側の処理です。
Leftノードを使い、元の文字列からドットの位置まで(ドット自体は含まず)を取り出します。
- In String: 元の文字列
- Count: Find Substringで得たインデックス値
例: Character.Melee.Warrior の最後の . が位置15だった場合、Leftで位置0~14の文字(Character.Melee)が返ります。
得られた文字列を戻り値「ParentTagName」にセットし、bSuccessをTrueにして返します。
ドットが見つからなかったFalse側では、bSuccessをFalseにして返します。
フォールバック対応の関数を作る
「TryPlayWithFallback」という関数を新たに作成します。
必要な引数は以下のとおりです。
- CharacterTagName : Name型(現在試しているキャラクタータグの文字列)
- ActionTagName : Name型(アクションタグの文字列)
- PlayActor : Actor型
関数の中身を組みます。
まず CharacterTagName と ActionTagName を「_」で連結し、Get Data Table Rowで検索します。
Get Data Table Rowノード周りを「PlayVoiceByTag」関数からコピペして持ってきます。
こちらの関数にはローカル変数「Sound Data Table」がないため、変数として必要であれば作成します。
Get Data Table Rowで見つかった場合はそのキューで再生します。
見つからなかった場合(Row Not Found側)では、GetParentTagName を呼び出して親タグを取得します。
bSuccess が True なら、取得した親タグで TryPlayWithFallback 自身を再帰的に呼び出します。
bSuccess が False なら、これ以上親タグがないので処理を終了します。この場合、デバッグ用に Print String で「フォールバック先が見つかりませんでした」といったメッセージを出しておくとデバッグに便利です。
この関数では自分自身を再び呼び出す処理を行っています。無限ループにならないよう終了条件(bSuccess が False のときに止まる)を必ず入れてください。
PlayVoiceByTagから呼び出す
元の「PlayVoiceByTag」関数を既に使用している場合、PlayVoiceByTag内でTryPlay with Fallbackを呼び出すことで、既存の再生処理を一括でフォーバック対応させられます。
動作確認
レベルに各種キャラクターを配置し、スキルアクションを実行してみます。
- 騎士のスキル使用時 → 「Character.Melee.Knight_Sound.Voice.Skill」がヒット → 騎士固有のスキルボイスが再生される
- 戦士のスキル使用時 → 「Character.Melee.Warrior_Sound.Voice.Skill」が見つからない → 親タグへ → 「Character.Melee_Sound.Voice.Skill」がヒット → 近接職共通のスキルボイスが再生される
- 戦士の攻撃時 → 「Character.Melee.Warrior_Sound.Voice.Attack」が見つからない → 親タグへ → 「Character.Melee_Sound.Voice.Attack」がヒット → 近接職共通の攻撃ボイスが再生される
データテーブルに固有の行があればそれを再生し、なければ自動的に親タグの共通ボイスを再生します。

















