プログラマーの卵の日記

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

【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が完全に消えました。

 

 

ゲームから学ぶ - ドラゴンズドグマ2

 

 

youtu.be

  • 一撃で倒したら戦闘BGMは再生されない
  • ポーンがダメージを受けても戦闘BGM開始される

 

 

 

youtu.be

  • 一定距離離れたら戦闘BGMが終了される
    • ポーンが戦闘中でも無関係
  • 戦闘に関係する敵HPUIも消える

 

 

 

youtu.be

  • 大型のみ小型のみなので分かりにくいけど、大型の敵がいれば大型用の戦闘BGMが流れるように思われる

 

 

 

youtu.be

  • プレイヤーとポーン関係なく、ダメージを与えるか・ダメージを受けたら戦闘BGMが開始されている
  • 雨などの環境音よりも戦闘BGMが優先される、もしくは音量が大きい

 

 

 

youtu.be

  • プレイヤーとポーン(パーティー)で違いはなく、同じ接触判定により接触SEが再生されている

 

 

 

 

ゲームから学ぶ - Rise of the Ronin

 

youtu.be

  • 警戒が黄色以上になったら戦闘BGMが始まっている
  • UISEは右側だったら右側から鳴っている(左なら左)

 

 

youtu.be

  • 警戒が黄色になると戦闘BGMが開始されている
  • 警戒が白から消えると戦闘BGMが終了される

 

 

youtu.be

  • 敵の警戒が黄色になると戦闘BGMが鳴り始める
  • 警戒が消えると戦闘BGMは終わる
  • 死亡している見方を発見すると敵の警戒が黄色になる
  • 敵にとって近くで物音がすると確認を行う

 

 

 

youtu.be

  • 靴で足音のSEが変わっている
  • 武器や服の装飾でSEが変わっている

 

【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);