- 警戒が黄色以上になったら戦闘BGMが始まっている
- UISEは右側だったら右側から鳴っている(左なら左)
- 警戒が黄色になると戦闘BGMが開始されている
- 警戒が白から消えると戦闘BGMが終了される
- 敵の警戒が黄色になると戦闘BGMが鳴り始める
- 警戒が消えると戦闘BGMは終わる
- 死亡している見方を発見すると敵の警戒が黄色になる
- 敵にとって近くで物音がすると確認を行う
- 靴で足音のSEが変わっている
- 武器や服の装飾でSEが変わっている
【UE5】【CRI ADX LE v2】基礎からおさらいしてみる vol.3 - プログラマーの卵の日記
こちらの続き
こちらのNo.22から学習
標準だと「Plugins」が選択されていないためにAtomが出てこないので選択する
Particle AttributesのPositionが自動的に設定される。
この時点でナイアガラのプレビューでも音が再生されるようになる。
カテゴリグループが異なればキューに複数設定できる都合上、この表示だと誤解する可能性が出そうですね。
上記だとPatch_Aisac_0をダブルクリックするとPatch_Aisac_0が表示される。
設定されているControlが表示されるのは良いね!
Wave Banksの設定可能有無で分かりそう
選択すると右側で詳細が分かるようになります。
ダブルクリックすると多少見やすくなります。
【UE5】【CRI ADX LE v2】基礎からおさらいしてみる vol.2 - プログラマーの卵の日記
前回の続き的な立ち位置
こちらのNo.15から学習始めます
カテゴリを用意して、キューを用意して、それぞれにカテゴリを設定しておく
unreal側でもカテゴリ設定状態が見れます。
指定したカテゴリのものすべてをミュートにする
適当に、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を渡せばいいように見える
公式のやり方を記載。
要はGameInstanceにAtomComponentを所持して、ゲームが終了されるまで破棄されないようにするというもの。
1. GameInstanceを作成
2. GameInstance内でAtomComponentを所持
3. レベルでAtomSoundBaseからAtomComponentをSpawnさせる
4. GameInstanceをキャストして取ってきて先ほどSpawnしたAtomComponentを渡す
レベル移動してもGameInstance内で再生しているAtomComponentがあるので維持される
?????それはどこで設定されてるんだ…??どっかのiniファイルなのかなぁ…。
uassetが読み込まれるときにキューシートがロードされる。
再生命令の時にキューシートのロードが行われる。
uassetが読み込まれるときにキューシートのロードがされる。
再生命令の時にキューシートのロードが行われる。
uassetの破棄でアンロードとなるよう。
ちょっと書き方違うだけでForce InlineとPrime onLoadが同じだったりでわけわからん…。
CriWare Unreal Engine: ADX チュートリアル No.20 : 広範囲のエリアをカバーする距離減衰の作成方法
こちらの方法らしいが、SourceActorsが設定できないのでまだ試運転かな…?
同時再生のずれが起きないのと、複数個所から鳴るけど一音となるためメモリ節約となるそう。
1. AtomMultiPositionComponentをアタッチさせる
2. レベル上に配置する
3. 発生させる箇所に適当なアクターを配置する
4. 配置したアクターから発生するように設定する
設定できない!
カテゴリ内のキュー数を制御できるようです。
近距離優先というので、新しく再生するキューはリスナーに近いキューから優先して再生するようになります。すでに再生済みのものには影響しないはずです。
キューごとで設定できます。
後着優先は、キュー制限数まで再生していた場合、一番古い再生を停止して新しく再生するものを必ず再生するようになります。
【UE5】【CRI ADX LE v2】基礎からおさらいしてみる vol.1 - プログラマーの卵の日記
前回の続き的な立ち位置。
今回はこれを主に見つつ勉強
Vol.1でC++から再生できるようにしたと思うのですが、3D音源だとアタッチもしていなければ座標も指定できていないので、0,0,0の座標から音が再生されるようになってしまいます。
変にハマったことですが、ループSEを再生しながら音源の位置移動は出来ないようで、位置移動したら再度停止して再生する必要があるみたいです。
publicにしてBPから弄れるようにします
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TObjectPtr<UAtomComponent> AtomComponent;
座標を常に更新するようにします。
Componentのノードとなり、AtomComponent特有のものではないです。
C++でもSetWorldLocation(FVector)で同じことができます。試行錯誤してBPに落ち着いただけです。
とりあえず見つけたやり方なので、正しいかはわからないです。
そもそもループSEをそういう風に扱わないかも。
Stop()という関数/ノードで止められます。
止める際には再生しているかチェックしたほうが安全かもしれない。
簡易確認用とかデバッグ用としては良いかもしれない。
上書きとなりAtom Craftでいくら設定しても変わらないということになってしまうので、最終的にはやらない方がいいようには思う。
Override Attenuationを有効にしてAttenuation関係のパラメータを設定すればそれなりに起こせる。
公式を見て行ってみたけど左右が逆…?一旦必要としていないのでスルー
Add NotifyのPlay Atom Soundというのをくっつけることで、アニメーションのタイミングで再生が行える。
Followを有効にしてAttach NameをSkeleton Treeにある名前を入れれば、そこから再生されるようになる。
専用の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);
色々あって、unrealからもadxからも離れていたので基礎からおさらいをしてみる。
「1から行いつつまとめる」というよりも「行ったことをまとめる」という形で記載をします。自分への備忘録です。
コードを乗せる便利なやつが無いので箇条書きを利用して記載します。
Unreal Engine 5.3.2
CRI ADX LE v2_01_00
Atom Craft v3.50.06
AtomCraftからビルドするプロジェクトに必ず1つ存在しているもの。
共通のデータとしてこういう部分の情報を保持している。
acbはacfを参照しているため、acfの更新があった場合はすべてのacbを再ビルドして再インポートする必要があります。
unrealプロジェクトでもProjectSettingで設定を必ずする必要がある。(インポート時に自動でされることが多い)
ストリーミングでない音データを保持しているものです。
以下のCueSheet_0とCueFirstなどがそれぞれ一つのacbファイルとして出力されます。
ストリーミング再生として指定された音の波形データです。
該当の音(acb)(キュー)を再生するためには必ず必要なものとなります。
ストリーミング設定にする方法としては、ターゲットコンフィグやマテリアルから設定ができます。
ストリーミング再生はちょっと手間いるので最後のほうに記載してます。
キューシート=.acb
CueSheet_0というのが一つのキューシート
.acbのuassetが一つのキューシート
キューシートの中にあるのが基本的にキュー
unrealでキューシートを開くと中に入っているキューが表示される
右上のループアイコンで表示されているのがループされるキュー
ループ指定はマテリアル側など
アクターにAtomComponentを持たせて再生。
Playノードを呼ぶだけ
パンタイプを3Dポジショニングにするだけ
範囲や残響などはAtomCraft側で細かく調整できるが面倒なので省略
unreal上でも範囲が表示される
再生関係のものが欲しいのでモジュールを追加
プロジェクト名.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++内で再生をしてみます。
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TObjectPtr<UAtomSoundBase> Sound;
private:
UPROPERTY(Transient)
TObjectPtr<UAtomComponent> AtomComponent;
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が出力されます。こちらを利用しなければストリーミングを含むキューは再生がされません。
※acbとawbが同じ階層だと同名のuassetを作る都合でインポートエラーが起きますが、別階層のフォルダであればインポートできます。
波形が無いのでわかりにくいですが、問題なく再生されるようになります。
パッケージの際にはawbのファイルも含めるようにしてください。
※誤っている可能性が非常に高いです。自分の考えをまとめることを目的としているため、それなりに順序不同・支離滅裂です。
Net Modeでサーバーモードを選択できます。
「Play Standalone」はサーバーを用いないものと思ってください。
クライアントのいずれかをゲームサーバーのホストとするような考えが「Play As Listen Server」です。
クライアントとは別にサーバーがある状態を「Play As Client」となります。
「Play As Listen Server」では、ホストが終了されると全クライアントも終了されます。
ですが、「Play As Client」では、ホストが存在しないのでどのクライアントが終了されてもゲームは終了されません。
オブジェクトを各クライアントで認識するためには、基本的にオブジェクトはサーバーで生成するようにする必要があります。
クライアントで生成したとしても、そのクライアントのみで描画され、ほかのクライアントでは描画されません。
仕組みとしては、サーバーで生成し、各クライアントにコピーされるという考えです。
オブジェクトを同期するため、アクターの詳細から「Replicates」を有効にします。
これにより、アクターの生成はサーバーと各クライアントで同期されます。
アクターをスポーンする場合、スポーンはサーバーのみで行わせます。
そのため、UEC++の場合「UKismetSystemLibrary::IsDedicatedServer(this);」という関数を用い、これがtrueの時のみ生成をさせます。
BPの場合は以下のノードがtrueの時のみ生成処理を呼びます。
そうしなければ、サーバー+各クライアント数のアクターが生成され、判定が不正確になってしまいます。
ゲーム中、アクターに変化を与え、全クライアントに同期させたくなります。
オブジェクトは基本的にサーバーで生成します。そのため、そのオブジェクト内で処理を行うと、サーバーには影響しますが各クライアント上では見た目的な変化は起きません。
サーバーのみの実行ではなく、各クライアントでも処理をさせるように対応させます。
UEC++では、処理をさせたい関数は以下のように宣言させます。
DuFunctionは定義する必要ありません。緑波線はほっときましょう。
オブジェクトのTickなどで適当に「PrintString」を接続させます。
そうすると出力表示に「Server: 」や「Client1: 」などと表示されます。これによりどこで生成され、どこで呼ばれているのか確認ができます。
UEC++の場合は「HasAuthority()」という関数で判断できます。
BPの方でも「Has Auhority」というノードがあります。
手話のみの人に対して、ボイスを追加して再生するオプションのようです。
ムービー中、字幕を見ないで声だけを聴く人にとっては便利ですね。
敵を見失ってもミニマップに出るので困らないですが、
倒し終わったかどうかの判断としてスローモーションされるのは分かりやすくていいなと思いました。
スローだと見やすいかも、移動キー入力時に移動先の車を決めて移動してるのかな
サーチを行うと、目的地に柱が立つようになって分かりやすくなってました。
この仕組み当たり前になってきたよなっていう感覚。
UIの文字とか見にくくはなるけど、明るさ調整の確認のためにオプションの開閉の手間が減って便利だなって。