#memo

indiedev太郎

つんのめりアニメーション

敵とか撃たれた時の反応のアニメーション

HalfLife2とかではこの反応はなくて、インパクト部位から出血やら火花が出るだけ
最近のリッチなゲームだと結構見かける

敵が人型と仮定して、まず当たる部位のバリエーションがある
分けると、頭部、胴体、腕(左右)、脚部(左右)の6部位で、めんどくさいので頭胴足程度でもよさそう

次に、方向があって、前後左右各斜めの8方向でブレンドする

この時、全体の長さはもちろん、開始ポーズと、ツメの位置みたいなのを一致させるようにすると綺麗なブレンドになる
また、極端なポーズを入れると、ブレンドが不自然になるので、統一性を持たせる

つんのめる足の順序は、左方向右方向からのインプットで変わってくるなどしていると、正面のアニメーションが1種類だときれいなブレンドが行われないので
左インプット用右インプット用でブレンドスペースを分けたりうまいことする

当たってくる弾薬にもバリエーションが有る、威力、爆発物、火炎瓶…
これでちょっと体が動く、1歩つんのめる、こける…のような、違った反応が出てくる

連続で攻撃があたった時、同一のアニメーションだと低予算感が漂うので、ここも変えるようにしたい

のように、バリエション地獄であり、HL2は完全に正しい


UEのサンプルでは、インパクト部位Belowの物理でこれを表現していたけれど、足がつんのめって動くみたいなのは流石にアニメーションじゃないと対応できないので、併用するのが良いと思いました

ルートモーションについて

ルートの差分をとって、キャラクタ移動に変換してくれる機能

ルートに回転のキーあったら回転しちゃうので、スケルトン構造は、原点にRootを作ってこれをルートモーション用として、移動のみ、その子にキャラルートを作るようにしておくと安心

キャラクタ側での適用方法は、AnimBP内のAnimPreviewEditorで、上部のEditDefaultsを選択して、RootMotionのところを、Root Motion from Everything にすると反映される
Montageの方はマルチプレイヤー用らしいけれど、機能制限があるらしく、単純な移動も反映されずよくわかりません

https://i.gyazo.com/23f43483cd5bb295c1bc1f96079a494b.png

参考
Unreal Engine | ルート モーション

NavMesh周りやる

NavMesh絶対しんどい、即死
箇条書き、即死


AAIController

AAIController::MoveTo
FAIMoveRequest型のMoveRequestを渡す
引数が正常か、もうゴールに到達してるかをチェックして、移動できるようであれば
1. FPathFindingQuery型のQueryを用意する
2. AAIController::PreparePathfinding関数を実行

AAIController::PreparePathfinding
1. 最新のUNavigationSystemを取得
2. ANavigationData* NavDataにNavSys->GetNavDataForProps(GetNavAgentPropertiesRef());


ANavigationData : AActor
TArray<FNavPathPoint> PathPoints;
TWeakObjectPtr<AActor> Base;

FPathFindingResult FindPath(const FNavAgentProperties& AgentProperties, const FPathFindingQuery& Query)
インライン関数


FPathFindingResult
FNavPathSharedPtr Path;
ENavigationQueryResult::Type Result;

検索したPath、その成否の構造体


FNavPathSharedPtr

FNavigationPathのスマートポインタ


FNavigationPath
TArray<FNavPathPoint> PathPoints;

Unreal Engine | FNavigationPath


FNavLocation

FVector Location;
NavNodeRef(uint64) NodeRef;

FNavPathPoint

FNavLocationを少し拡張

FPathFindingQueryData
TWeakObjectPtr<const UObject> Owner;
FVector StartLocation;
FVector EndLocation;
FSharedConstNavQueryFilter QueryFilter;
FNavAgentProperties NavAgentProperties;
int32 NavDataFlags;
uint32 bAllowPartialPaths : 1;
FPathFindingQuery : public FPathFindingQueryData
TWeakObjectPtr<const ANavigationData> NavData;
FNavPathSharedPtr PathInstanceToFill;
FNavAgentProperties NavAgentProperties;
FAIMoveRequest

AITypes.hで定義されている構造体
メンバ変数は
・AActor* GoalActor
・FVector GoalLocation
あとこまごまで、目的地を指定するかんじである
Unreal Engine | FAIMoveRequest

UNavigationSystem : public UBlueprintFunctionLibrary

Unreal Engine | UNavigationSystem


UNavigationSystem::FindPathToLocationSynchronously

FPathFindingResult UNavigationSystem::FindPathSync(FPathFindingQuery Query, EPathFindingMode::Type Mode)
Result = Query.NavData->FindPath(Query.NavAgentProperties, Query);

PathFollowingComponent


dtNavMeshQuery

ここに具体的な経路探索のアルゴリズムやらなんやらが

Unreal Engine | dtNavMeshQuery


ARecastNavMesh : public ANavigationData

honmei



<NavigationTypes.h>

FMovementProperties
uint32 bCanCrouch:1;
uint32 bCanJump:1;
...

AIがしゃがんだり泳いだりできるのかどうかやらを記す構造体


FNavAgentProperties : public FMovementProperties
float AgentRadius;
float AgentHeight;
float AgentStepHeight;
...

AIの移動性能とかを記す構造体


FNavDataConfig : public FNavAgentProperties
FName Name;
FColor Color;
TSubclassOf<ANavigationData> NavigationDataClass;
...

実際に使用するnavmeshのクラスや色やらを設定する構造体
NavigationSystemでは、RecastNavMeshがNavigationDataClassとされておる


わかrないでうs

Boids

ABZU最高!→Boidsやろう!→糞重い!!

https://i.gyazo.com/bba715ac2ded3aedb0740496895411e5.gif

計算減らせそうな部分
・2,3段階くらいのレベルつくって、そこで計算をさせて、魚自身はそこの値見て動くだけにする
・プレイヤーとの距離で処理の精度を調節する
・Separationの簡略化でそれっぽくが難しい
・単純にメッシュ増えると重くなる(2000くらいから辛い)

https://i.gyazo.com/e003da415e6a98aa8f6f0054ab510b60.gif

あのイワシ玉どうやってんだろう…

プレイヤー名の表示、参加者一覧の取得

https://i.gyazo.com/1bc48631950e8f0b26b3b92e735410bb.png

・ゲーム参加直後はログイン処理がある
・ゲーム開始時クライアント側では、あるはずの変数やインスタンスがちゃんと存在している保証はない

参加者一覧は、各クライアントで、レベルにあるPlayerStateをイテレーターで名前やらPingを取って表示したら良いのだけれど、例えばこれをゲーム開始直後に生成してしまうと、サーバーから人数分すべてのPlayerStateを受信出来ているかどうかが確実ではないなど、ちょっと表示を行う処理のタイミング考えないと行けない
単にDelay置いても良さそうだけれど、100%ではないので、もう少し堅牢な設計がやりたい

よくわかるフロー図
https://i.gyazo.com/9a91f68a0078cf8467241711ce42a372.png

プレイヤー上部の名前表示には、そのプレイヤーのPlayerStateと、そのプレイヤーのログイン初期化処理が終了していることが必要で、自分のフローでは、PlayerPawnのスポーン完了をログインフェーズの最後としている
なので、"PlayerStateのAPawn* ControlledPawn変数が値を受け取った瞬間 = 当該ユーザーのログイン、初期化処理が完全に終了したことを、クライアントで認識した瞬間" であるので、"OnRepControlledPawn関数が発火する = 当該ユーザーの情報に安全にアクセスできる"という感じでやっている

なんかもう少し処理を単純にできそうだけれど、とりあえずこれで安定している