プログラマーの卵の日記

備忘録になってます!小難しそうなことから超簡単なことまでやってます!!

【UE5】【CRI ADX LE v2】基礎からおさらいしてみる vol.4

 

 

 

概要

【UE5】【CRI ADX LE v2】基礎からおさらいしてみる vol.3 - プログラマーの卵の日記

こちらの続き

 

 

 

公式

CriWare Unreal Engine: ADX

こちらのNo.22から学習

 

 

 

Niagaraから再生

1. 「+」ボタンからAtom Playerを追加

 

2. Particle SpawnにD&Dして追加

 

3. Particle Spawnの「+」からPlay Persistent Atomを追加

標準だと「Plugins」が選択されていないためにAtomが出てこないので選択する

 

4. PlayAtomという変数が出来てるのでParticle SpawnにD&Dして追加


5. PlayAtomのDetailsからチェックをTrueにする

 

6. UpdateのほうにUpdate Persistent Atomを追加

 

7. Update Persisten AtomAtom PlayerをセットしてLocationを設定する

Particle AttributesのPositionが自動的に設定される。

この時点でナイアガラのプレビューでも音が再生されるようになる。

 

 

 

.acfアセットから情報

カテゴリ

カテゴリグループが異なればキューに複数設定できる都合上、この表示だと誤解する可能性が出そうですね。



グローバルAISAC

 

上記だとPatch_Aisac_0をダブルクリックするとPatch_Aisac_0が表示される。

設定されているControlが表示されるのは良いね!

 

Aisac Controls

 

セレクタ

 

 

 

.acbアセットから情報

キュー設定

 

ストリーミングを含むか

Wave Banksの設定可能有無で分かりそう

 

キューアセットから情報

選択すると右側で詳細が分かるようになります。

 

ダブルクリックすると多少見やすくなります。

 

簡易ですが、得られる情報
  • キュー名
  • キュータイプ
  • ループ設定
  • 3Dポジショニングかどうか
  • カテゴリー設定
  • AISAC設定
  • 残響・反響
  • ストリーミングかどうか

 

 

 

 

 

 

 

 

 

 

 

【UE5】【CRI ADX LE v2】基礎からおさらいしてみる vol.3

 

 

概要

【UE5】【CRI ADX LE v2】基礎からおさらいしてみる vol.2 - プログラマーの卵の日記

前回の続き的な立ち位置

 

 

 

公式

こちらのNo.15から学習始めます

game.criware.jp

 

 

カテゴリに関する関数

カテゴリを用意して、キューを用意して、それぞれにカテゴリを設定しておく

 

unreal側でもカテゴリ設定状態が見れます。

 

一時停止

 

停止

 

音量変更

 

ミュート

指定したカテゴリのものすべてをミュートにする

 

 

 

AISACと関連する関数

適当に、Atom Craftで音量を弄るAISACをキューに追加

 

1. Aisac Control型の変数を作成

2. 該当するコントロールを変数に設定

3. Set Aisac Control Valueを使用してキューとコントロールを紐づける

 

AISACだけ弄るとかいうのは出来なそう。

 

コードの方
  • void UAtomComponent::SetAisacControlValue(const FAtomAisacControl& AisacControl, float Value)
    {
        if (FAtomRuntime* AtomRuntime = GetAtomRuntime())
        {
            FAtomAisacControlParameterInfo ParamInfo;
            ParamInfo.Control = AisacControl;
            ParamInfo.Value = Value;

            DECLARE_CYCLE_STAT(TEXT("FAtomThreadTask.AtomSetAisacControlValue"), STAT_AtomSetAisacControlValue, STATGROUP_AtomThreadCommands);
            AtomRuntime->SendCommandToActiveSounds(AtomComponentID, [ParamInfo](FAtomActiveSound& ActiveSound)
            {
                ActiveSound.SetAisacControl(ParamInfo);
            }, GET_STATID(STAT_AtomSetAisacControlValue));
        }
    }

 

  • USTRUCT(BlueprintType)
    struct CRIWARECORE_API FAtomAisacControl
    {
        GENERATED_BODY()

    public:

        FAtomAisacControl()
            : ID(INDEX_NONE)
        {}

        FAtomAisacControl(FName InName, int32 InID)
            : Name(InName)
            , ID(InID)
        {}

        bool operator==(const FAtomAisacControl& Other) const
        {
            return ID == Other.ID;
        }

        bool operator!=(const FAtomAisacControl& Other) const
        {
            return !(*this == Other);
        }

        /** Name of the AISAC control. */
        UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "AISAC")
        FName Name;

        /** Unique Atom Craft ID of the AISAC control. */
        UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "AISAC")
        int32 ID;
    };

    inline uint32 GetTypeHash(FAtomAisacControl A) { return static_cast<uint32>(A.ID); }

 

AISACコントロールIDを渡せばいいように見える

 

 

 

DSPバスは後回し…

 

 

 

レベル移動しても再生を維持する

公式のやり方を記載。

要はGameInstanceにAtomComponentを所持して、ゲームが終了されるまで破棄されないようにするというもの。

 

1. GameInstanceを作成

2. GameInstance内でAtomComponentを所持

3. レベルでAtomSoundBaseからAtomComponentをSpawnさせる

4. GameInstanceをキャストして取ってきて先ほどSpawnしたAtomComponentを渡す

レベル移動してもGameInstance内で再生しているAtomComponentがあるので維持される

 

 

 

キューシートのリソースのライフタイム

?????それはどこで設定されてるんだ…??どっかのiniファイルなのかなぁ…。

 

Force Inline:

uassetが読み込まれるときにキューシートがロードされる。

 

Retain on Load:

再生命令の時にキューシートのロードが行われる。

 

Prime on Load:

uassetが読み込まれるときにキューシートのロードがされる。

 

Load on Demand:

再生命令の時にキューシートのロードが行われる。

 

uassetの破棄でアンロードとなるよう。

ちょっと書き方違うだけでForce InlineとPrime onLoadが同じだったりでわけわからん…。

 

 

 

一つの音源が複数個所から再生(AtomMultiPositionComponentが正しく使えないので保留)

CriWare Unreal Engine: ADX チュートリアル No.20 : 広範囲のエリアをカバーする距離減衰の作成方法

こちらの方法らしいが、SourceActorsが設定できないのでまだ試運転かな…?

 

以下途中メモ

同時再生のずれが起きないのと、複数個所から鳴るけど一音となるためメモリ節約となるそう。

 

1. AtomMultiPositionComponentをアタッチさせる

 

2. レベル上に配置する

3. 発生させる箇所に適当なアクターを配置する

 

4. 配置したアクターから発生するように設定する

設定できない!

 

 

 

発音数制御

カテゴリごとの制限設定

カテゴリ内のキュー数を制御できるようです。

近距離優先というので、新しく再生するキューはリスナーに近いキューから優先して再生するようになります。すでに再生済みのものには影響しないはずです。

 

キューごとの制限設定

キューごとで設定できます。

後着優先は、キュー制限数まで再生していた場合、一番古い再生を停止して新しく再生するものを必ず再生するようになります。

 

 

 

【UE5】【CRI ADX LE v2】基礎からおさらいしてみる vol.2

 

 

概要

【UE5】【CRI ADX LE v2】基礎からおさらいしてみる vol.1 - プログラマーの卵の日記

前回の続き的な立ち位置。

 

 

 

公式

今回はこれを主に見つつ勉強

game.criware.jp

 

 

C++で用意したAtomComponentで3D再生

Vol.1でC++から再生できるようにしたと思うのですが、3D音源だとアタッチもしていなければ座標も指定できていないので、0,0,0の座標から音が再生されるようになってしまいます。

変にハマったことですが、ループSEを再生しながら音源の位置移動は出来ないようで、位置移動したら再度停止して再生する必要があるみたいです。

 

アクター.h

publicにしてBPから弄れるようにします

  • public:  

        UPROPERTY(EditAnywhere, BlueprintReadWrite)
        TObjectPtr<UAtomComponent> AtomComponent;

 

アクターBP

座標を常に更新するようにします。

Componentのノードとなり、AtomComponent特有のものではないです。

C++でもSetWorldLocation(FVector)で同じことができます。試行錯誤してBPに落ち着いただけです。

 

 

 

ループSEを再生しながら再生位置を動的に変化させる

とりあえず見つけたやり方なので、正しいかはわからないです。

そもそもループSEをそういう風に扱わないかも。

 

 

 

再生をやめる

Stop()という関数/ノードで止められます。

止める際には再生しているかチェックしたほうが安全かもしれない。

 

 

 

BP側で距離減衰の設定を上書き

簡易確認用とかデバッグ用としては良いかもしれない。

上書きとなりAtom Craftでいくら設定しても変わらないということになってしまうので、最終的にはやらない方がいいようには思う。

 

Override Attenuationを有効にしてAttenuation関係のパラメータを設定すればそれなりに起こせる。

 

 

 

リスナーの位置をカメラではなくキャラの位置と向きで連動

公式を見て行ってみたけど左右が逆…?一旦必要としていないのでスルー

 

 

 

アニメーションから音を再生

Add NotifyのPlay Atom Soundというのをくっつけることで、アニメーションのタイミングで再生が行える。

Followを有効にしてAttach NameをSkeleton Treeにある名前を入れれば、そこから再生されるようになる。

 

 

 

Anim Notifyから音を再生

専用のAnim Notifyを作成し、socketの位置に生成をして再生をさせる。

ちょっとした処理を加えたい場合に有効そうに思われる。

直前と同様にアニメーションにこのAnim Notifyを設定させる。

 

 

 

シーケンサーから音を再生

シーケンサー触ることないから色々雑。

 

TrackからAtom Trackを選択

 

Atomに右にある「+」からキューを選択して配置できる。

ただし、ループ設定の曲でもループされないようなので、終了までループしたければ最後まで個数分配置する必要があるように思われる。

 

 

 

生成してアタッチする

再生の生成は基本的にAtom Sound Baseから行います。

Spawn Sound AttachedでAtom Componentを生成しながらアタッチが行えるようです。

 

 

 

停止・一時停止

SetPausedがtrueで一時停止、falseで再開

Stopが停止(終了)

Atom Componentから命令が出来る。

  •     /** Stop sound, issue any delegates if needed */
        UFUNCTION(BlueprintCallable, Category = "Atom|Components|Sound")
        void Stop();

        /** Cues request to stop sound after the provided delay, stopping immediately if delay is zero or negative */
        UFUNCTION(BlueprintCallable, Category = "Atom|Components|Sound")
        void StopDelayed(float DelayTime);

        /** Pause sound playing, issue any delegates if needed */
        UFUNCTION(BlueprintCallable, Category = "Atom|Components|Sound")
        void SetPaused(bool bPause = true);

 

 

 

 

 

【UE5】【CRI ADX LE v2】基礎からおさらいしてみる vol.1

 

 

概要

色々あって、unrealからもadxからも離れていたので基礎からおさらいをしてみる。

「1から行いつつまとめる」というよりも「行ったことをまとめる」という形で記載をします。自分への備忘録です。

コードを乗せる便利なやつが無いので箇条書きを利用して記載します。

 

 

環境

Unreal Engine 5.3.2

CRI ADX LE v2_01_00

Atom Craft v3.50.06

 

 

公式

game.criware.jp

 

 

.acfファイル

AtomCraftからビルドするプロジェクトに必ず1つ存在しているもの。

共通のデータとしてこういう部分の情報を保持している。

acbはacfを参照しているため、acfの更新があった場合はすべてのacbを再ビルドして再インポートする必要があります。

 

unrealプロジェクトでもProjectSettingで設定を必ずする必要がある。(インポート時に自動でされることが多い)

 

 

 

.acb

ストリーミングでない音データを保持しているものです。

以下のCueSheet_0とCueFirstなどがそれぞれ一つのacbファイルとして出力されます。

 

 

 

.awb

ストリーミング再生として指定された音の波形データです。

該当の音(acb)(キュー)を再生するためには必ず必要なものとなります。

 

ストリーミング設定にする方法としては、ターゲットコンフィグやマテリアルから設定ができます。

ストリーミング再生はちょっと手間いるので最後のほうに記載してます。

 

 

 

キューシート

キューシート=.acb

CueSheet_0というのが一つのキューシート

.acbのuassetが一つのキューシート

 

 

 

キュー

キューシートの中にあるのが基本的にキュー

 

unrealでキューシートを開くと中に入っているキューが表示される

 

 

 

ループ設定されるキュー

右上のループアイコンで表示されているのがループされるキュー

 

ループ指定はマテリアル側など

 

 

 

BPでキューの再生

アクターにAtomComponentを持たせて再生。

 

Playノードを呼ぶだけ

 

 

 

3Dポジショニング

パンタイプを3Dポジショニングにするだけ

範囲や残響などはAtomCraft側で細かく調整できるが面倒なので省略

 

unreal上でも範囲が表示される

 

 

 

C++でキュー再生

再生関係のものが欲しいのでモジュールを追加

プロジェクト名.Build.cs

  • public class EternalADXLEV2C : ModuleRules
    {
        public EternalADXLEV2C(ReadOnlyTargetRules Target) : base(Target)
        {
            PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

            PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "EnhancedInput", "CriWareCore" });
        }
    }

 

データはuassetとなるので、BPから再生するQを指定できるようにし、c++内で再生をしてみます。

 

アクター.h

  • class UAtomComponent;
    class UAtomSoundBase;
  • <<<
  • public:

        UPROPERTY(EditAnywhere, BlueprintReadWrite)
        TObjectPtr<UAtomSoundBase> Sound;

    private:
        UPROPERTY(Transient)
        TObjectPtr<UAtomComponent> AtomComponent;

 

アクター.cpp

  • #include "Atom/AtomComponent.h"
    #include "Atom/AtomSoundBase.h"
  • <<<
  • void ANormalActor::BeginPlay()
    {
        Super::BeginPlay();

        AtomComponent = NewObject<UAtomComponent>(GetWorld());

        if (IsValid(Sound) && IsValid(AtomComponent))
        {
            AtomComponent->SetSound(Sound);
        }

        if (IsValid(AtomComponent))
        {
            AtomComponent->Play(0.0f);
        }
    }

 

BPのアクター側で右のDetailsのほうでキューを設定できるようになるので、再生したいものを設定すれば完了です。


ややこしそうな変数名だったので二つの変数(UAtomSoundBase型 Sound/SoundVer2)作ってみてこんな感じ

 

 

 

ストリーミング設定のキュー再生

ストリーミング設定されると.awbが出力されます。こちらを利用しなければストリーミングを含むキューは再生がされません。

 

1. .acbと.acfが全て同じ階層に置いてあるとして、.awb用のAWBフォルダを用意します。

 

2. AWBフォルダの中に.awbをインポートさせます。

※acbとawbが同じ階層だと同名のuassetを作る都合でインポートエラーが起きますが、別階層のフォルダであればインポートできます。

 

3. ストリーミングのacbのWaveBanksにファイル指定が出来るようになっているので、先ほどのawbを指定します。

 

波形が無いのでわかりにくいですが、問題なく再生されるようになります。

パッケージの際にはawbのファイルも含めるようにしてください。

 

 

【UE5】Play As Clientについて学習

※誤っている可能性が非常に高いです。自分の考えをまとめることを目的としているため、それなりに順序不同・支離滅裂です。

 

 

Unreal Engineのサーバーについて

Net Modeでサーバーモードを選択できます。

「Play Standalone」はサーバーを用いないものと思ってください。

 

クライアントのいずれかをゲームサーバーのホストとするような考えが「Play As Listen Server」です。

クライアントとは別にサーバーがある状態を「Play As Client」となります。

 

「Play As Listen Server」では、ホストが終了されると全クライアントも終了されます。

ですが、「Play As Client」では、ホストが存在しないのでどのクライアントが終了されてもゲームは終了されません。

 

 

オブジェクト

オブジェクトを各クライアントで認識するためには、基本的にオブジェクトはサーバーで生成するようにする必要があります。

クライアントで生成したとしても、そのクライアントのみで描画され、ほかのクライアントでは描画されません。

仕組みとしては、サーバーで生成し、各クライアントにコピーされるという考えです。

 

レベル上に配置。サーバーで生成し、各クライアントと同期

オブジェクトを同期するため、アクターの詳細から「Replicates」を有効にします。

これにより、アクターの生成はサーバーと各クライアントで同期されます。

 

 

Actor Spawnでゲームに生成。サーバーで生成し、各クライアントと同期

アクターをスポーンする場合、スポーンはサーバーのみで行わせます。

そのため、UEC++の場合「UKismetSystemLibrary::IsDedicatedServer(this);」という関数を用い、これがtrueの時のみ生成をさせます。

BPの場合は以下のノードがtrueの時のみ生成処理を呼びます。

そうしなければ、サーバー+各クライアント数のアクターが生成され、判定が不正確になってしまいます。

 

 

オブジェクトの同期

ゲーム中、アクターに変化を与え、全クライアントに同期させたくなります。

 

オブジェクトは基本的にサーバーで生成します。そのため、そのオブジェクト内で処理を行うと、サーバーには影響しますが各クライアント上では見た目的な変化は起きません。

 

サーバーのみの実行ではなく、各クライアントでも処理をさせるように対応させます。

UEC++では、処理をさせたい関数は以下のように宣言させます。

UFUNCTION(NetMulticast, Reliable)
void DoFunction();
void DoFunction_Implementation();

void AAA::DoFunction_Implementation()
{
    // サーバーと各クライアントで実行する処理
}

DuFunctionは定義する必要ありません。緑波線はほっときましょう。

 

 

サーバーかクライアントか確認

オブジェクトのTickなどで適当に「PrintString」を接続させます。

そうすると出力表示に「Server: 」や「Client1: 」などと表示されます。これによりどこで生成され、どこで呼ばれているのか確認ができます。

 

 

生成した対象内のみで処理を実行

UEC++の場合は「HasAuthority()」という関数で判断できます。

BPの方でも「Has Auhority」というノードがあります。

 

 

 

ゲームから学ぶ - スパイダーマン2からいろいろ

 

オプションの手話ナレーションについて

youtu.be

手話のみの人に対して、ボイスを追加して再生するオプションのようです。

ムービー中、字幕を見ないで声だけを聴く人にとっては便利ですね。

 

 

 

ミッションの敵全部倒したときにスローモーション

youtu.be

敵を見失ってもミニマップに出るので困らないですが、

倒し終わったかどうかの判断としてスローモーションされるのは分かりやすくていいなと思いました。

 

 

 

敵撃破時にSE

youtu.be

  • 撃破時にSE
  • 同じスパイダーマンでも顔アイコンで字幕を分けている
  • 水掛かったら画面濡れる

 

 

 

車上移動

youtu.be

スローだと見やすいかも、移動キー入力時に移動先の車を決めて移動してるのかな

 

 

 

目的地に柱

youtu.be

サーチを行うと、目的地に柱が立つようになって分かりやすくなってました。

 

 

 

電話途中で戦闘に入ると途切れ、戦闘が終わると途中から会話が開始

youtu.be

この仕組み当たり前になってきたよなっていう感覚。

 

 

 

オプションの明るさ

 

UIの文字とか見にくくはなるけど、明るさ調整の確認のためにオプションの開閉の手間が減って便利だなって。

 

ゲームから学ぶ - 数値とBGMの変化

 

youtu.be

 

良い名称が思いつかないのでそのままですが、数値が0に近くなるとBGMがくぐもっていくようになっているようです。

 

ある程度遊んだのですが、最初のチュートリアルだけかもしれない