愛をもってゲームをつくるゴリラのブログ

UE5勉強中のゴリラがいろいろ頑張ります。

GameplayEffect - その1 GameplayEffect と Application 編

こんにちは、ごりです。

今日はGameplayEffectに関しての説明です。

Effectと聞くと火を出したりといった見た目の影響を想像する人が多いですが、

今回は内部のパラメータに影響を与えるといった意味で用いられる機能です。

 

f:id:m-goolee-y:20181124070701p:plain

カテゴリだけで9個あります。

設定項目が多いので複数回に分けて書いていきたいと思います。

 

その中から、今回はGameplayEffect,Application について

説明していきたいと思います。

f:id:m-goolee-y:20181124071431p:plain

まず、GameplayEffectについて

 

  • DurationPolicy 

パラメータに影響を与える時間を設定できます。

Instant : Effectが適用された瞬間に一度だけパラメータに影響を与えます。

Infinite : Effectが適用されてから取り消されるまでの間、

永続的に影響を当てます。

HasDuraion : Effectが適用されてから一定時間パラメータに影響を与えます。

 

Infinite,HasDuration にすると Period というカテゴリが追加されます。

f:id:m-goolee-y:20181124081415p:plain

Period : ここで指定した数値秒ごとに、パラメータの値が変更されます。

Execute Periodic Effect on Application : ここの値がfalseだと値が変更されるのは

指定秒経ってからになります。true の場合は 適用されてすぐに値が変更され、

指定秒経ったらまた値の変更がされるようになります。

デフォルトでは true になっています。

  • Modifiers

f:id:m-goolee-y:20181124072911p:plain

Modifiersはパラメータに与える数値の変化量を設定できます。

 

Attribute : 影響を与えるパラメータです。

        AttributeSet(そのうち記事にします) にある値を指定できます。

ModifierOp : 影響を与える際の値の計算方法です。

Modifier Magnitude : パラメータの変化量

SourceTags : パラメータに影響を与える発生源となったもののタグ

       Required Tags : ここで指定されたタグが全てあれば、対象に影響を与える。

       Ignore Tags :    ここで指定されたタグが全てあれば、対象に影響を与えない。

TargetTags :  パラメータに影響を与える対象となったもののタグ

       Required Tags : ここで指定されたタグが全てあれば、対象に影響を与える。

       Ignore Tags :   ここで指定されたタグが全てあれば、対象に影響を与えない。

 

  • Executions

f:id:m-goolee-y:20181124074149p:plain

Executionsは独自の計算方法を設定できます。

 

Calculation Class : 

GameplayEffectExecutionCalculation クラスを継承した、独自の計算クラスです。

Conditional GameplayEffects :  

       Effect Class : ここで指定した計算式でパラメータへの影響に成功した際に

           対象に適用するGameplayEffect

       Required Source Tags : 発生源にここに指定されたタグがあれば対象に適用する

 

  • ConditionalGameplayEffects

     Effect Class : このGameplayEffectが適用された際に

            対象に適用する別のGameplayEffect

        Required Source Tags : 発生源にここに指定されたタグがあれば対象に適用する

 

続いて、Apllication についてです。

f:id:m-goolee-y:20181124075702p:plain

  • Chance to Apply to Target 

このGameplayEffectを適用させる確率、1の場合は必ず適用

  • Execute Periodic Effect on Application

GameplayEffectCustomApplicationRequirement クラスを継承して、

適用可能かどうかの判定方法を設定できます。

 

以上が、設定項目 GameplayEffect、Applicationの説明になります。

また、間違っている点ありましたら、ご連絡いただけると幸いです。

ではでは。 

GameplayAbility - タグ編

お久しぶりです、ごりです。

 

3連休ですが家に引き込まって記事書き続けます。

今日は GameplayAbility についてです。
こちらは4.20から追加されたUE4のSampleプロジェクトのActionRPGで

使用されている機能ですね。

今日は使い方というよりも、設定項目の説明になります。
使い方を知りたい方は


おかわりはくまいさんがすごくわかりやすく解説していますので、
以下の記事を参考にしてください。

okawari-hakumai.hatenablog.com


アビリティを作成した際の、Default設定のこちらのTagsの項目についての説明です。

f:id:m-goolee-y:20181123114154p:plain

 

  • Ability Tags 

f:id:m-goolee-y:20181123115005p:plain

こちらのノードで、アビリティを実行するためのタグになります。

  • Cancel Ability with Tag

ここに設定されているタグと一致していて、実行中のアビリティはすべて、

中断されます。

  • Block Abilities with Tag

ここに設定されたタグと一致しているアビリティは、このアビリティを実行中には、

実行されません。

  • Activation Owned Tags

このアビリティが実行されると、ここに設定されたタグを持ちます。

  • Activation Required Tags

このアビリティを実行するためには、ここで設定されたタグを持っている

必要があります。

  • Activation Blocked Tags

ここで、設定されたタグを持っていると、このアビリティは実行されない。

 

ここから下の設定項目は [ TryActivateAbilityWithTag ]ではなく、

別の呼び出し方法にかかわってきます。

 

f:id:m-goolee-y:20181123120429p:plain

こちらのノードを使う際 Payload というピンがあります。

こちらはGameplayEventDataという構造体になっています。
この構造体を作成する中に、

f:id:m-goolee-y:20181123120726p:plain

Instigator Tags, Target Tags がありますので、ここに設定したタグが

かかわってきます。

  • Source Required Tags

Instigator Tags に設定されたタグが、ここに設定したタグに含まれていたら、

このアビリティが実行されます。

  • Source Blocked Tags

Instigator Tags に設定されたタグが、ここに設定したタグに含まれていたら、

このアビリティが実行されません。

  • Target Required Tags

Target Tags に設定されたタグが、ここに設定したタグに含まれていたら、

このアビリティが実行されます。

  • Target Block Tags

Target Tags に設定されたタグが、ここに設定したタグに含まれていたら、

このアビリティが実行されません。

 

以上が、GameplayAbility のTagsの説明になります。


まだDefaultの設定の中には、別の設定項目もあるのですが、

GameplayEffect というのが関わってきますので、今日はここまでにします。
GameplayEffectについては明日書かせていただきます。

 

一通りの説明が終わったら、GameplayAbilityを使って作った簡単な機能の

プロジェクトを公開したいですね。

 

また、今回の説明で間違っている点などありましたら、連絡していただけると

ありがたいです。 ではでは。

 

空中を歩くAIをつくってみる

こんばんは、ごりです。

2か月ぶりの更新です。

今回は飛行AIを作ってみたいと思います。

ナビメッシュだと地上のAIには使えるのに空中にいるAIには使えないんですよね...

 

www.unrealengine.com

 

上記のようなプラグインも出ているみたいですが、

今回はこのプラグインを使わずに作っていきたいと思います。

そしてナビメッシュも使いません。

 

UE4をやっている人なら一度は見たことのあるこのノードを使います。

  

f:id:m-goolee-y:20180903194747p:plain

 

これをつかってビヘイビアツリーのMoveToタスクを作ると、空中のキャラクターも動いてくれるようになります。

 

作り方は、まずビヘイビアツリーの

f:id:m-goolee-y:20180903193338p:plain

[新規タスク]のBTTask_BlueprintBase をクリックして、新しくブループリントクラスを作ります。

クリックするとビヘイビアツリーと同じフォルダに

f:id:m-goolee-y:20180903193533p:plain

こいつが作られるので、名前を BTTask_CustomMoveTo

に変更しておきましょう。

変更したらダブルクリックして開きます。

 

次に関数のオーバライド一覧から

RecieveExecuteAIをクリックします。

f:id:m-goolee-y:20180903201658p:plain

 

タスク開始時の処理を作っていきます。

ブラックボードに移動先の座標が書かれているとして、

[BlackBoard Key Selector]型の変数を追加します。

名前は NextLocation とします。

f:id:m-goolee-y:20180903195323p:plain

また移動先までの距離(Length)の変数も追加しておきます。

変数を追加したら下記の画像の通りに、ノードをつないでいきます。

f:id:m-goolee-y:20180903202739p:plain

 

開始時の処理はこれで完了です。

続いて移動処理を書いていきます。

関数のオーバーライド一覧から[Recieve Tick AIをクリックします。

f:id:m-goolee-y:20180903201535p:plain

 

ここで作る処理は、移動後の移動先までの残り距離の割合を計算し、閾値以下ならこのタスクは成功として返す処理となっています。

f:id:m-goolee-y:20180903203129p:plain

 

はい、これで自作のMoveToタスクが出来上がりました。

 

過去記事のEQSを使って動かしてみました

この時のAIのCharacter Movement はFlyingの状態にしてください。

 

www.youtube.com

 

ちゃんと空中を歩いていますね。

アニメーションを飛行アニメーションに変えたらそれっぽくなるかもしれないですね。

ちなみにこのカスタムMoveToはパス検索などしていないので、現状障害物をよけて進んだりはできません。

障害物をよける処理については、また後日に書きたいと思います。

 

ではまた。 

 

追記

CEDEC2018で空中のパス探索についての講演がありましたね。

それについても、そのうち実装出来たらと思います。

 

 

BehaviorTree でのMoveToタスクのカクつきを緩和してみる

お久しぶりです。ごりです。

1年ぶりの投稿です。

先日UE4勉強会in大阪(https://ue4study-osaka.connpass.com/event/93325/)にて

EQSについて講演してきました。

そのときに、BehaviorTreeのMoveToタスクについてのカクつきについて

質問があったので今回はそれについての記事にな

ります。

 

1年前の記事になりますが、このEQSを使って解説していきます。

 

goolee.hatenablog.com

 準備としてBlackBoardKeyにVectorDestination を追加しておいてください。

ここにEQSで計算した目標地点を格納します。

f:id:m-goolee-y:20180801210006p:plain

 

カクつくパターンのBehaviorTreeとして、以下のようにしました。

RunEQSQueryタスクにRandomWalk、BlackboardKeyにDestinationを設定します。

MoveToタスクの Blackboard keyにDestinationを設定します。

 

f:id:m-goolee-y:20180801210338p:plain

これで実行してみると...

f:id:m-goolee-y:20180801211207g:plain

 

カクついているのがわかると思います。

この対処法について、サービスで目標地点の近くにきたら目標地点を更新するという手法を提案しました。

そのサービスに中身について見ていきます。

BehaviorTreeの上部にある[新規サービス]からBTService_BlueprintBaseをクリック、新しくサービスを作成します。

作成したサービスの名前は UpdateDestinationとします。

f:id:m-goolee-y:20180801213249p:plain

 

サービスの更新間隔は以下のように設定してください。

f:id:m-goolee-y:20180801213514p:plain

新しく作成したサービスを開くと、イベントグラフには何もありません。

まずはカスタムイベントでEQSを実行するイベントを作成します。

RunEQSQueryノードでランダムウォークを設定し、

EQSの計算終了時に、目標地点をBlackBoardKeyに格納と目標地点までの距離を計算しています。

f:id:m-goolee-y:20180801213705p:plain

 

カスタムイベントを追加だけでは実行されません。

関数のオーバーライドから ReceiveSearchStartAI を選択します。

RecieveSearchStartAIではEQSの実行を行います。

今回の実装ではこのイベントは一回だけ呼ばれます。

f:id:m-goolee-y:20180801214308p:plain

 

次に関数のオーバーライドから RecieveTickAI を選択します。

f:id:m-goolee-y:20180801214558p:plain

 

RecieveTickAIでは残りの移動距離をチェックし一定の比率以下になったら目標地点を更新するようにしています。

f:id:m-goolee-y:20180801215046p:plain

 

これでサービスは完成です。

BehaviorTreeのRunEQSタスク削除し、以下のように設定しなおします。。

f:id:m-goolee-y:20180801215309p:plain

 

またMoveToの設定で BlackboardKey下の 

Observed Blackboard Value Tleranceを有効にする必要があります。

f:id:m-goolee-y:20180801215647p:plain

 

これで実行すると...

 

f:id:m-goolee-y:20180801215423g:plain

 

カクつきが緩和されたと思います。

それとBehaviorTreeがすっきりしましたね。

 

この手法以外にもカクつきをなくす方法はあると思います。

みなさんもいろいろ試してみてください。

間違っている点などありましたら、ご指摘いただけるとありがたいです。

 

ではまた。

 

 

 

EQSでランダムウォーク

こんばんは、goolee(ごり)です。

今日はEQSを用いたランダムウォークについて。

ランダムには動いているので、良しとしました。

では「EQS_RandomWalk」の名前のEQSを作ります。

f:id:m-goolee-y:20170815191602p:plain

今回用いたGenerator は「Circle」Generator です。

変更する部分は円の半径、生成するアイテム間の距離、トレースモードの3つです。

今回は

円の半径を300 。

生成するアイテム間の距離を DataBinding の設定を 「Randomnumber」 で

最小値を「100」最大値を「400」。

TraceData のTraceMode を 「None」にしました。

f:id:m-goolee-y:20170815191712p:plain

アイテム間の距離をランダムにすることで、プレイヤーの正面にアイテムが生成されない場合を作り、これによって前に進み続けて行きどまりになったら方向転換という動きだけにならないようにしました。

TraceModeを「None」にした理由ですが、

TraceModeが「Navigation」のままだと目の前に壁があると、壁の手前にアイテムが生成されてしまい、トレースのテストに影響が出てしまうと考えました。

f:id:m-goolee-y:20170815192956p:plain

なので「None」にして目の前に壁があっても壁の奥にアイテムが生成されるようにしました。

f:id:m-goolee-y:20170815193125p:plain

 

次に今回行ったテストは

・現在向いている方向にある点かどうか

・視界にはいっているかどうか

・到達可能かどうか

の3つです。

 

まず 現在向いている方向にある点かどうか です。

これには 「Dot」テストを行います。

変更する部分はTestPurposeを「ScoreOnly」に変えるだけです。

f:id:m-goolee-y:20170815195350p:plain

これは数学の内積ですね。

 

プレイヤーが向いている方向ベクトル(赤色)と

プレイヤーからアイテムまでのベクトル(青色)で内積を行っています。

赤色青色の矢印のなす角度Θが小さいほど内積の値は大きくなります。

つまり内積の値が大きくなるほど、向いている方向のアイテムになるということです。

 

f:id:m-goolee-y:20170815195244p:plain

 

では次に 視界にはいっているかどうか です。

これは前回書いた記事で行った 「Trace」テストを行います。

TestPurposeを「FilterOnly」にし Boolの一致のチェックをはずします。

f:id:m-goolee-y:20170815200644p:plain

f:id:m-goolee-y:20170815200850p:plain

最後に 到達可能かどうか です。

これには 「PathFinding 」のテストを行います。

これはアイテムまでの移動経路があるかどうかを判断してくれます。

変更する部分は TestPurposeを 「FilterOnly」に変えるだけです。

f:id:m-goolee-y:20170815201332p:plain

これでランダムウォークのEQSは完成です。

 

あとはこのようなビヘイビアツリーを作成すれば動きます。

移動のタスクは自作のものを使用していますが、「MoveTo」のタスクでも動くと思います。

f:id:m-goolee-y:20170815201637p:plain

 実際に動かした動画がこちらになります。


EQSでランダムウォーク

 

 

なにかおかしな点ありましたらコメントお願いします。

ではまた。

EQSで簡単な敵の探索をしてみる

お久しぶりです。ごりです。

今日は簡単な敵探索をEQSを使って実装したいと思います。

 

まず「EQS_FindEnemy」の名前のEQSをつくります。

f:id:m-goolee-y:20170811235343p:plain

 

今回使うGeneratorは 「ActorOfClass」です。

半径はお好みで設定。今回僕は半径1000で行っています。

探索する相手クラスを「BP_Enemy」としています。

f:id:m-goolee-y:20170811235953p:plain

 とりあえず現状でEQSを実行すると以下のようになります。

f:id:m-goolee-y:20170812000541p:plain

 赤色を探索を行うキャラクター、青色を敵キャラクターとしています。

敵キャラの位置にアイテムが生成されていることがわかります。

 

このアイテムの中からテストを行って一つの敵キャラクターに絞っていきます。

今回僕が行ったテストは

・プレイヤーから一番離れている敵

・プレイヤーから見える敵

の2つです。

 

まずプレイヤーから一番離れている敵のテストを実装していきます。

テストの中から「Distance」を選択。

TestPurposeを「ScoreOnly」にするだけです。

今回は一番離れているてきなので。SocringEquationを「Linear」のままにしていますが、

一番近い敵を探索したい場合は「InverseLinear」を使うと良いです。

設定し終わるとこのようになります。

f:id:m-goolee-y:20170812001745p:plain

 f:id:m-goolee-y:20170812002004p:plain

 

プレイヤーから離れるほど大きなスコアがついています。

では次にプレイヤーから見える敵のテストです。

これは「Trace」のテストを追加します。

TestPurposeを「FilterOnly」にし、

「Boolの一致」のチェックを外します。

f:id:m-goolee-y:20170812002726p:plain

f:id:m-goolee-y:20170812003437p:plain

これだと正しく計算されているかわからないので障害物をおいてみます。

f:id:m-goolee-y:20170812003509p:plain

プレイヤーから見えない敵キャラはスコア計算対象外となっていますね。

これで簡単な敵探索のEQS完成です。

f:id:m-goolee-y:20170812003658p:plain

このようなビヘイビアツリーを作成して動かすとこのように動きます。

youtu.be

 

ここ間違ってるなどありましたらコメントお願いします。

次回はランダムウォークでも作成したいと思います。

 

ではまた。

ウィジェットブループリント内でゲームパッドの入力をとれるようにした

どうも、ごりです。

 

今日はウィジェットブループリント内でのゲームパッドの入力の取り方を

僕なりにやってみました。

 

まずブループリントクラスを作成のところから、「ブループリントマクロライブラリ」を作成を選択して

f:id:m-goolee-y:20161112124913p:plain

親クラスは 「UserWidget」 で作成します。

名前は 「 GamePadInputMacroLibrary 」 とします。

f:id:m-goolee-y:20161112124953p:plain

 

今回はゲームパッドの左サムスティックで上下左右の入力とAボタンで決定するといった入力を取得したいと思います。

作成したマクロライブラリを開いて

 

まず右側の+マークをクリックして

「L_ThumStickY」「L_ThumStickX」「Button_A」と3つマクロを用意します。

 f:id:m-goolee-y:20161112125706p:plain

 

「L_ThumStickY」で説明します。

インプットに実行ピンを追加し名前を「Execute」

アウトプットピンに実行ピンを3つ追加し、「Up」「Down」「Neutral」とします。

f:id:m-goolee-y:20161112130253p:plain

 

次から処理になります。

f:id:m-goolee-y:20161112130501p:plain

「GetPlayerController」ノードから「Get Inpur Analog Stick State」を取得します。

Witch Stick は 左スティックなので 「CAS Left Stick」のままでいいです。

 

僕はサムスティックをある程度傾けた時に入力判定を取りたいので

閾値の絶対値を 0.9にしています。

 f:id:m-goolee-y:20161112130933p:plain

 

あとはStickYの値が閾値以上の場合は「Up」に

閾値以下の場合は「Down」に

それ以外は「Neutral」につなげばこれで完成です。

f:id:m-goolee-y:20161112132042p:plain

 

「L_ThumStickR」も同じように作ります。

f:id:m-goolee-y:20161112132210p:plain

f:id:m-goolee-y:20161112131926p:plain

 

次は「Button_A」についてです。

インプットには 実行ピンで「Execute」

アウトプットには 実行ピンで「Pressed」「NotPressed」

を追加します。

f:id:m-goolee-y:20161112132540p:plain

 

先ほどは「GetPlayerController」から「GetInputAnalogStickState」を取得していましたが、今度は「IsInputKeyDown」を取得します。

f:id:m-goolee-y:20161112132854p:plain

 

最後に ReturnValueが True なら Pressed

False なら Released につなげば 完成です。

 

f:id:m-goolee-y:20161112133045p:plain

 

あとは、入力を取得したいウィジェットブループリント内の

イベントティックに以下のようにつなげば入力を取得することができます。

 

f:id:m-goolee-y:20161112133657p:plain

 

これは毎フレーム判定しているので、InputAxis のような動作になります。

InputActionのようにしたい場合は、

このように DoOnce を使えば InputAction のようにすることもできます。

f:id:m-goolee-y:20161112134040p:plain

 

今回はマクロライブラリを使っての取得でしたが、

マクロライブラリを使わずにウィジェットブループリント内の仕組みで、取得する

方法があるみたいなので、いつかそれについてもやってみたいと思います。

 

これ間違っている、こうしたほうがもっと簡単などあれば

コメントお願いいたします。