2024年の振り返りと2025年の目標
2024年
何やったかなって、基本的に記事書くかゲーム作るかしてないのでそれをまとめてみました(会社を除く)
Zenn
記事
UEとADXLEでマスター音量を考慮した音量オプションの対応を考えてみた
ADX/ADX LE勉強会 vol.1で得た知見として、SetBusVolumeを用いればもっと良いやり方出来るんじゃないかと思ったりしたけど、試せてないな…
本
Wwiseに関しては触る機会が無くなったので更新減りましたね…
UEとかADXは会社都合で更新しづらくなりましたが、プライベートで何かしらのきっかけで気になって検証したものを更新しましたね、今年も続ける気持ち!
はてなブログ
一番下の月別アーカイブから確認!
8月から更新頻度減ってるのは仕事の忙しさと比例して面白いですね…
あとは知見が増えてきたこともあって、この音楽演出は珍しい!っていうゲームに気づけなくなりましたね…相変わらず新しいゲームは発掘してます!
Youtube
動画リンク多いので画像で…



遊んだゲームで音演出について動画投稿してますね
ちなみにメタファーはまだクリアしてないです…がマリルイ始めました
Qiita
【UE5】AI触って身についた自分の知見 #UnrealEngine - Qiita
アドカレのやつだけでした
自分だけかもしれませんが、Qiitaってまぁまぁ知見のある人が見てるイメージ多くて恐れ多いんですよね……
新しいこと
Notion
NotionでUEC++に関するメモをまとめてました、UEC++とか言いながらADXについてもまとめてたりしてました
ただ、Zennでまとめるのが楽だったのと8月から仕事が忙しくなったこともあって更新頻度はほぼ無くなりましたね…
情報としては色々載ってるので、備忘録としてたまに見つつ更新するかもです!
lit.link
X(旧Twitter)のプロフィール用ですが、やってることをまとめました
それぐらいですね
気持ち総括
会社は異動ばかりでバタバタするし、プライベートも忙しくなってきたし、なんか大変な2024年でしたね
とはいえ、新しいこととか学びとか増えたのでめっちゃ充実してました
ただ、期待されている以上の力は発揮できていない歯がゆさはあるので、2025年頑張りたいですね
2025年
目標
立てようと思ったんですが、会社のこととかちらついて書きづらい…やめる
20代最後を満喫しよう!
ADX / ADX LE勉強会 vol.1 レポート
概要
https://connpass.com/event/337976/
勉強会でメモしたものです
※通院帰りだったので懇親会出てません…ハイチュウ貰いました~
各講演
クロスフェードをいくつかやってみる
AISACでフェード切り替え
- トラックごとで設定が必要になる
- 汎用的ではなく、特定のキューのみ
キューリミットによるもの
- エンベロープのリリースタイムとアタック?を用いるやり方
- AISACとセレクタには影響を受けないので、AISACとセレクタは気にせず設定ができる
- プログラマ的には再生の呼び出しだけになる
- プレビュー画面などの使用に向いている
セレクターによる遷移 ダカーポ
- 必ず次曲が頭から再生となる
- トラックごとでセレクターの用意が必要になる
セレクター レガート
カスタムエフェクトプラグインでAtom Craftをいい感じにする
※初めての情報ばかりで理解しきれなかったので誤ったメモが多いと思います
- カスタマエフェクトプラグインで検索してみて
- カスタムエフェクトによってAtomCraftがよく落ちる
- VST3プラグイン
- エフェクトプラグインのみ使用できる
- ゲーム側では利用できず、atomcraft上でのみ
- Socalabs
- NDItools
CRI ADXを触り始めて1年、反省と学び、今後の展望
事例
- 1~5のボイスをランダムキューによってランダム再生しようとしたが、それぞれがテキストと紐づける必要が出たのでランダムキューは使用できなかった
- 収録側とデータの命名規約を決めずに進めていたため、データ名からどういった内容のものなのか分からず想定以上に工数が嵩んだ
- AtomCarftロボットを用いてはいたが、特定のキューのみではなく全キューに対する処理だったため、処理時間がかかりすぎてしまっていた
- QA期間になっても無音で遊ぶ人がいるからバグ報告が遅い(来ない)
- ちょっとした音の違和感は無視されがち
- メモリを節約したいからキューシートを細かくする必要がある
ADXチュートリアルのリニューアルについて
ADX for Unityの機能を拡張する様々なスクリプトのご紹介
- ...Asr.SetBusVolumeでマスター音量調整している
- デバッグでデータ表示の拡張を行っていた
- カテゴリなどを表示できるようにしていた
インゲームカットシーンでのサウンド考察(Unreal Engine)
問題
- シーケンサー中のカメラによって距離減衰で聞こえなくなったりした
対策
- シーケンサー用のデータを別途用意した
- リスナーの位置をカメラではなくキャラの位置にした
- キャラの位置にし続けていたら問題が起きたので、状況によって切り替えられるようにした
- カメラのズームでは、距離減衰で聞こえないことがあったので、リスナー位置を良い感じに調整させた
- リスナー位置が分かりにくくなったので、デバッグ表示できるようにした
所感
クロスフェードのキューリミットを用いるやり方は認識外だったので試してみたいと感じました
カスタムエフェクトプラグイン関係が初見すぎてまったく理解できなかったので、調べて知識つけようかと思いました
SetBusVolumeは見直してみます
【UE5】Subsystem(GameInstanceSubsystem)について学習してまとめ
概要
SubSysmteについて学習しようかと思いました
基本的に参考サイトを見たものを自分が分かるようにまとめてみただけです
参考
【UE4】Subsystem, GAS, DataAssetを活用して実装した会話システムについて雑多に書いてみた - ぼっちプログラマのメモ
【UE5】Subsystem(サブシステム)を使ってみよう! - main() blog
合わせて読んだページ
UE5/UE4 C++でクラス(Class)を生成する(NewObject) 凛(kagring)のUE5/UE4とゲーム制作と雑記ブログ
DOFI LAB BLOG: UE4: 親のBegin Playなどのイベントを呼び出す
UE4 プログラミングサブシステムを試してみる #UnrealEngine4 - Qiita
内容
おかずさんの記事に載っているslideshareが一番わかりやすいです。
SubSystemとしては色んなものがあるようです。
簡易に作成
ゲーム中常駐しているようなものが欲しいため、GameInstanceSubSystemを継承して作ることにしました。
記事を参考に、「コンストラクタ」「初期化」「破棄」「Tick」「簡易な関数」を用意してみました。
#pragma once
#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "MyGameInstanceSubsystem.generated.h"
/**
*
*/
UCLASS()
class UE52ADXV1LE_API UMyGameInstanceSubsystem : public UGameInstanceSubsystem, public FTickableGameObject
{
GENERATED_BODY()
/// コンストラクタ
UMyGameInstanceSubsystem();
/// 初期化
virtual void Initialize(FSubsystemCollectionBase& Collection);
/// 破棄
virtual void Deinitialize();
/// Tickを使用するために必須
virtual TStatId GetStatId() const override
{
RETURN_QUICK_DECLARE_CYCLE_STAT(UMyGameInstanceSubsystem, STATGROUP_Tickables);
}
/// Tick
/// Tickを使用するためにはFTickableGameObjectを継承する必要がある
virtual void Tick(float DeltaTime) override;
UFUNCTION(BlueprintCallable, BlueprintPure)
int32 GetNumber() { return Number; }
private:
int32 Number = 0;
};
#include "MyGameInstanceSubsystem.h"
UMyGameInstanceSubsystem::UMyGameInstanceSubsystem()
{
}
void UMyGameInstanceSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
}
void UMyGameInstanceSubsystem::Deinitialize()
{
Super::Deinitialize();
}
void UMyGameInstanceSubsystem::Tick(float DeltaTime)
{
}
これだけで基本要素は出来上がり、下記のような形でどこからでも呼び出せるようになるようです。


c++側では以下の形で呼び出せそうです。
適当なアクターで呼び出してみました。
#include "MyActor.h"
#include "MyGameInstanceSubsystem.h"
void AMyActor::BeginPlay()
{
Super::BeginPlay();
UGameInstance* GameInst = GetWorld()->GetGameInstance();
if (!IsValid(GameInst))
{
return;
}
auto MySub = GameInst->GetSubsystem< UMyGameInstanceSubsystem>();
if (!IsValid(MySub))
{
return;
}
UE_LOG(LogTemp, Log, TEXT("UMyObject::BeginPlay: %d"), MySub->GetNumber());
}
処理をSubsystem内でなく外で行う
Subsystemに処理を書けばいいのですが、処理を外で行う方法を試してみます。
色んな人がHelperという名前でこういうことをやってたみたいです。
同じ命名規約をしていたため、そういうクラスがあるのかと思ってましたが、ただのUObjectです。
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "MyGameInstanceSubsystemHelper.generated.h"
/**
*
*/
UCLASS()
class UE52ADXV1LE_API UMyGameInstanceSubsystemHelper : public UObject
{
GENERATED_BODY()
UMyGameInstanceSubsystemHelper();
public:
void Show();
};
#include "MyGameInstanceSubsystemHelper.h"
UMyGameInstanceSubsystemHelper::UMyGameInstanceSubsystemHelper()
{
}
void UMyGameInstanceSubsystemHelper::Show()
{
UE_LOG(LogTemp, Log, TEXT("UMyGameInstanceSubsystemHelper::Show()"));
}
作成したクラスをSubsystem側で使用できるように作成します。
#pragma once
#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "MyGameInstanceSubsystemHelper.h"
#include "Tickable.h"
#include "MyGameInstanceSubsystem.generated.h"
/**
*
*/
UCLASS()
class UE52ADXV1LE_API UMyGameInstanceSubsystem : public UGameInstanceSubsystem, public FTickableGameObject
{
GENERATED_BODY()
/// コンストラクタ
UMyGameInstanceSubsystem();
/// 初期化
virtual void Initialize(FSubsystemCollectionBase& Collection);
/// 破棄
virtual void Deinitialize();
/// Tickを使用するために必須
virtual TStatId GetStatId() const override
{
RETURN_QUICK_DECLARE_CYCLE_STAT(UMyGameInstanceSubsystem, STATGROUP_Tickables);
}
/// Tick
/// Tickを使用するためにはFTickableGameObjectを継承する必要がある
virtual void Tick(float DeltaTime) override;
public:
UFUNCTION(BlueprintCallable, BlueprintPure)
int32 GetNumber() { return Number; }
UPROPERTY(Transient, BlueprintReadOnly)
TObjectPtr< UMyGameInstanceSubsystemHelper> SubsystemHelper;
private:
int32 Number = 0;
};
#include "MyGameInstanceSubsystem.h"
UMyGameInstanceSubsystem::UMyGameInstanceSubsystem()
{
}
void UMyGameInstanceSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
SubsystemHelper = nullptr;
SubsystemHelper = NewObject< UMyGameInstanceSubsystemHelper>();
if (IsValid(SubsystemHelper))
{
SubsystemHelper->Show();
}
}
void UMyGameInstanceSubsystem::Deinitialize()
{
Super::Deinitialize();
SubsystemHelper = nullptr;
}
void UMyGameInstanceSubsystem::Tick(float DeltaTime)
{
}
実際にゲームをプレイしてログを確認すると、UE_LOGのログが出ていることが確認できます。つまり、問題なく作成されていることが確認できます。
これで処理を分けられます。
Subsystem内の関数ではなく、Helperの関数を呼び出して行うこともできます。

BPで作成した関数を利用する
Subsystemが常駐されるものです。
基本的には、Subsystemに対して何かを処理を行うものかと思います。
ですが、それではBP側で対応ができないです。
以下では、Subsystemに処理を加えて何かをするのではなく、SubsystemHelperのBPで処理を加えて行う方式です。
このやり方なら、c++側とBP側で命名かぶらなければ自由に追加し放題です。
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "MyGameInstanceSubsystemHelper.generated.h"
/**
*
*/
UCLASS(Abstract, Blueprintable, meta = (ShowWorldContextPin))
class UE52ADXV1LE_API UMyGameInstanceSubsystemHelper : public UObject
{
GENERATED_BODY()
UMyGameInstanceSubsystemHelper();
public:
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
void Initialize();
virtual void Initialize_Implementation();
UFUNCTION(BlueprintCallable)
void Show();
};
#include "MyGameInstanceSubsystemHelper.h"
UMyGameInstanceSubsystemHelper::UMyGameInstanceSubsystemHelper()
{
}
void UMyGameInstanceSubsystemHelper::Initialize_Implementation()
{
UE_LOG(LogTemp, Log, TEXT("UMyGameInstanceSubsystemHelper::Initialize_Implementation()"));
}
void UMyGameInstanceSubsystemHelper::Show()
{
UE_LOG(LogTemp, Log, TEXT("UMyGameInstanceSubsystemHelper::Show()"));
}
Subsystem側でHelperのBPを所持するようにします。
#pragma once
#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "MyGameInstanceSubsystemHelper.h"
#include "Tickable.h"
#include "MyGameInstanceSubsystem.generated.h"
/**
*
*/
UCLASS()
class UE52ADXV1LE_API UMyGameInstanceSubsystem : public UGameInstanceSubsystem, public FTickableGameObject
{
GENERATED_BODY()
/// コンストラクタ
UMyGameInstanceSubsystem();
/// 初期化
virtual void Initialize(FSubsystemCollectionBase& Collection);
/// 破棄
virtual void Deinitialize();
/// Tickを使用するために必須
virtual TStatId GetStatId() const override
{
RETURN_QUICK_DECLARE_CYCLE_STAT(UMyGameInstanceSubsystem, STATGROUP_Tickables);
}
/// Tick
/// Tickを使用するためにはFTickableGameObjectを継承する必要がある
virtual void Tick(float DeltaTime) override;
public:
UFUNCTION(BlueprintCallable, BlueprintPure)
int32 GetNumber() { return Number; }
UPROPERTY(Transient, BlueprintReadOnly)
TObjectPtr< UMyGameInstanceSubsystemHelper> SubsystemHelper;
private:
TSubclassOf< class UMyGameInstanceSubsystemHelper> SubsystemHelperClass;
int32 Number = 0;
};
#include "MyGameInstanceSubsystem.h"
UMyGameInstanceSubsystem::UMyGameInstanceSubsystem()
{
static ConstructorHelpers::FClassFinder< UMyGameInstanceSubsystemHelper> BluePrintFile(TEXT("/Game/BP_MyGameInstanceSubsystemHelper"));
if (BluePrintFile.Class) {
SubsystemHelperClass = (UClass*)BluePrintFile.Class;
}
}
void UMyGameInstanceSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
SubsystemHelper = nullptr;
if (SubsystemHelperClass)
{
SubsystemHelper = NewObject< UMyGameInstanceSubsystemHelper>(GetTransientPackage(), SubsystemHelperClass);
}
if (IsValid(SubsystemHelper))
{
SubsystemHelper->Initialize();
}
}
void UMyGameInstanceSubsystem::Deinitialize()
{
Super::Deinitialize();
SubsystemHelper = nullptr;
}
void UMyGameInstanceSubsystem::Tick(float DeltaTime)
{
}
BPを作成させます。ファイル検索の都合上で名前は決まってます。


試しにc++からオーバーライドした関数と、BPで関数を用意してみます。


ゲームをプレイでInitializeが呼ばれることが確認できます。
また、BPで作った関数も呼び出せます。


【UE5.4.3】Audio Insightsを試してみた
資料
Unreal Engine 5.4 リリース ノート | Unreal Engine 5.4 ドキュメンテーション | Epic Developer Community
有効化
デフォルトでは、AudioInsightsプラグインは無効とされています
実験段階とされて、バージョンは1.0のようです


コード
何ができるのかよくわからないけどUnrealInsightsを使ったときにAudio関係も出てくるのかなと思いつつ、コードもあるので見れそう

Audio Insightsの表示

適当な音を再生してみるとこんな感じです

ゲームから学ぶ - The Crew Motorfest
概要
「The Crew Motorfest」が期間限定で無料プレイできたので遊んでみました
思ったことまとめつつ、サウンドオプション周りを中心に書きます
雑多に思ったこと箇条書き
- 他プレイヤーの車も走っているようです。音もあり、描画もされ、(多少の)動機もされているようですが、当たり判定はないようです。ぶつかるような場面だと半透明のような描画となってすり抜けます
- NPCの車もいますが、速度はそれほど出ていなくて車もそれほど走っていないような感覚です。ぶつかると停止した感じと同じくらい速度が落ちます。すれすれを走るとポイントが得れるようです
- 雨や水たまりでよく滑ります。正直滑りすぎて腹立ちますが、正しい挙動ではあるので受け入れられはします。ただ滑りすぎるので腹立ちます
- 止まっててもエンジンは止まらなくて鳴り続けるようです
- 巻き戻しによってNPC車と重なっても、そのNPC車とは当たり判定がないようです
- 天候と雲があってない時があるかも
序盤ゲームプレイ
オプション
オプションにあるサウンドの個々の内容を確認します
オプションにあるサウンドの内容と詳細
- マスター音量 ※全体的なゲームの音量を調整します
- マシン音量 ※マシンの主音量を調整します
- BGM音量 ※ミュージックの主音量を調整します
- ゲームプレイの音楽 ※ドライビング時またはゲームプレイのムービーで流れる音楽の音量を調整します
- フェスティバルの音楽 ※ゲーム内のスピーカーなど、ゲームプレイ内の音源から流れる音楽の音量を調整します
- ストーリーの音楽 ※事前にレンダリングされたムービーやビデオで流れる音楽の音量を調整します
- ボイス音量 ※すべての音声の音量を調整します
- システム音量 ※UIのサウンドと通知の音量を調整します
- 効果音音量 ※サウンドエフェクトの音量を調整します
- 環境音 ※ゲーム内のあらゆるサウンドスケープや周囲のサウンドの音量を調整します
- 接触音 ※あらゆるセッションの音量を調整します
- ダイナミックレンジ ※お使いのオーディオ環境に合わせて、ダイナミックレンジとイコライゼーションのプリセットから選択してください
- ヘッドホン/TVスピーカー/ホームシネマ
- コントローラーオーディオ ※コントローラーのスピーカーから流れるオーディオの有効/無効を切り替えます。この機能を使用するには、オーディオ機能付きのコントローラが検出されており、ヘッドホンを使用していないことが条件となります。
- 音量 ※コントローラーのスピーカーから流れる音の音量を調整します。
- CARA ※コントローラーのスピーカーから流れるCARAの音声の有効/無効を切り替えます
- 配信者モード ※有効にすると、著作権フリーの楽曲だけが流れ、合法的に配信プラットフォームでゲーム内容をシェアできるようにします
- CARA音声(AIアシスタント)
- ガイダンス ※フリードライブ中のCARAによるガイダンスのセリフをすべて有効化/無効化(パーソナルアシスタントツールの使用時に流れる台詞)
- PLAYLIST紹介 ※フリードライブ中のCARAによるPLAYLIST紹介の台詞をすべて有効化/無効化(未クリアのイベントやコンテナへの走行時に流れる台詞)
- 短い台詞 ※CARAの短い台詞(巻き戻しとクリーンドライビング時)をすべて有効化/無効化
【UE5】AIに関するTips・知見・振り返り
概要
作成中のゲームのAIを部分的に抜粋してTipsのようなものをまとめたものです
作成中、ということもあってそれなりに端折ってたりします
思い出しながら書いてるので順序不同です
必要最低限のもの


最低限、ビヘイビアツリーとブラックボード、AIコントローラーが必要です
必要最低限のこと
AIとして動かすアクター

作成したAIコントローラーをアクターのAI Controller Classというところに設定をします
ビヘイビアツリーにブラックボードを設定

ビヘイビアツリーのほうでブラックボードを設定します
プレイヤーを追う例
ブラックボードのキー

ブラックボードにキーを追加することができます
これを利用して色々制御を入れたりします
今回、PlayerActorというObjectのキーを用意しておきます
ビヘイビアツリーで制御

Blackboard Based Conditionというのを用い、PlayerActorに中身があるかどうかで制御させます
PlayerActorが空でなければ、下へ処理が続きます
AIコントローラーでPlayerActorに値を入れる

AIコントローラーでBlackboardが取れるので、KeyNameにPlayerActorを入れつつ、Object Valueに中身を入れます

上記のように何も指定しなければ、中身が空扱いとなり、先ほどのBlackboard Based Condition以下は処理がされなくなります
ビヘイビアツリーのTips
Move To

Objectキーの値を入れられます
指定されたアクターのそばまで向かいます
Selector

つなげたノードの左から順番に処理がされるようにあんります
Default Focus(Set default focus)

設定したObjectキーの対象を注視するようになります

右クリックしてサービスを追加にあります
Simple Parallel

左に接続したノードをメインとして、右に接続したノードをサブとして行います
左に接続したノードが終了するまで右に接続したノードが行われ続けるみたいな感じです
例えば、左に接続したノードがターゲットに近づくという命令だった場合、ターゲットに近づいて終わるまで右に接続したノードも行われ続けるようになります
左に接続したノードが即終わるようなものだった場合、右に接続したノードもすぐ終わります
Wait

指定した秒だけビヘイビアツリー全部の処理が止まります
自作タスク

BTTaskNodeまたはBTTask_BlueprintBaseというのを利用して作成します、自分は後者です

Receive Execute AIかReceive Tick AIとかを用いてこんな感じでいじります

インスタンス編集可能にして変数を追加すれば、ビヘイビアツリーで指定ができます

自作したものをビヘイビアツリーで呼べます
自作デコレーター

BTDecoratorまたはBTDecorator_BlueprintBaseというものを利用して作成します、自分は後者です

Perform Condition Check AIという関数から、boolの返り値で返します

自作したものをビヘイビアツリーで呼びます
返り値がtrueだったら下の処理が走り、falseだったら下の処理は呼ばれません
AIコントローラーのTips
変数
変数の作成

作成自体は普通のアクターと同じように作成できます
変数の値を外からいじる

AIを設定したアクター内のほうでAIコントローラーが呼べるので、特定の条件になったら値を変えるということができます
AIキャラクターに検知させるアクター

AIPerceptionStimuliSourceというのを設定する必要があります
グランツーリスモ7の車効果音を中心的に見てみる
車効果音のオプション
グランツーリスモ7のサウンドオプションからいじれる項目は以下のものです
いじれると言っても、音量を0~100に変えれるとかではなく、音量を増やすか減らすかできる程度です
オプション
-5.0 ~ +5.0で調整できるので、一つの項目を+5.0にしてそれ以外を-5.0にしてどういうものか聞いてみます
同じレースで同じ車でプレイした動画を乗せます
自車エンジン音
youtu.be自分の車のエンジン音が大きくなるようです。
ただ、体感ではあまり変化を感じられませんでした。
トランスミッションノイズ
youtu.be正直よくわからない内容なので検索 トランスミッションとは(オイル・故障警告灯)|チューリッヒ
ギアチェンジとかに関わる音だと解釈。
画面真下が回転数とギア(と速度)に関わるもので、こちらの変動に関する音だと思われました。
スキール音
youtu.beタイヤが地面にこすれると鳴る音をスキール音というようです。
実際に、急カーブやダートを走るときに音が大きく感じられました。
他車エンジン音
youtu.be前の車というより後ろから迫ってくる他車のエンジン音が強く感じられました。
ただ、左右のどちらにいるのかは音だけだと分かりづらかったので、窓ガラスを見て把握する感じになるかなと思いました。
チューニングで車乗り換え時
youtu.be車を切り替えるたびにエンジン音を聞かせてくれます。数秒操作しないとUIが完全に消えました。