読者です 読者をやめる 読者になる 読者になる

I From Japan Staff Blog

I From Japan の開発者ブログです

初めまして、ヨシゾウです。UE4(BluePrint)

プログラミング Unreal Engine 4

 

blog.i-fromjapan.com

 

本日より始まりました。 I From Japan のスタッフブログ。ブログの具体的な説明は 八代君が後々、投稿してくれると思いますのでそちらを読んで下さい。
僕のブログでは、毎日の進捗とUnreal Engine 4 を使っていて躓いたところとそれの解決策を書いていきます。

早速、今日のお題は

 「 Hit Stop のネットワーク対戦での実装です」


そもそも、Hit Stop とは

アクションゲームなどでよく実装されている処理なのですが
攻撃を敵に当てたときに、一瞬だけプレイヤーと敵の動きを止めることで攻撃の当たった感を出す処理です。
 
 
 
僕の場合はこのマクロの中で Bool ”Do Hit Stop” Float”Hit Stop Time”を攻撃ボタンを押したときに変数に格納しています。
 

f:id:ifromjapan:20160930221849p:plain

 
 
 
それをApply Damage が呼び出される直前に参照して
さらにプレイヤーのキャラクタークラスにも作ってある
同じ名前の変数にそれぞれを代入します。

f:id:ifromjapan:20160930221939p:plain

 
 
この画像ではBoolはチェックマークを入れているだけですが...
 
そしてその後にSet_Time__Dilationというイベントを呼び出しています。
 
 
僕のプロジェクトの場合、このプログラムが実行されているのが
「サーバーだけでスポーンさせてReplicateしている」武器のBluePrint内なので
 
 
一回イベントを飛ばして、それをマルチキャストにしなければその後のプレイヤーを一瞬止める処理がサーバー上でしか反映されません。

*オフラインプレイの場合はイベントを飛ばさずに直接繋いでもらえれば大丈夫です。
 
 
 

このイベントで実行しているのが、攻撃を行ったプレイヤーを一瞬だけ止める処理です。
 
 
いろいろやり方はあるのですが、僕はこの方法でやりました。
 
 

Set Custom Time Dilation

 

 

これは、指定されたターゲットだけの時間を管理するノードです。
つまり、このターゲット以外はこれに影響されないということです。
 
オンラインにうってつけですね。
 

オンラインプレイでは今後どんな風なプログラムを組むかわからないので
Character MovementからGet Character Owner をしました。


 
それの前につながってる"Player Ref Multi"は変数に格納している、この武器を所持しているキャラクターの情報です。
 
*オフラインならば普通にGet Player Character で大丈夫です。
 
 
このノードをまず、0.0に設定して

先程、攻撃の時に設定したHit Stop Timeの秒数だけDelayを入れて

再び1に戻します


 
これで攻撃をしたプレイヤーは 攻撃が当たった瞬間に指定した時間だけ動きが止まります。
 
 
 
 
 
次に攻撃を受けたプレイヤーにHit Stop をする方法に移ります。
 
 
先程の、攻撃を行うときは、攻撃をする者が誰なのかわかっていたのに対し
 
 
攻撃を受けるほうがそれがプレイヤーなのか、敵なのか、
 
はたまた地面で燃えている火なのかわかりません
 
(火から受けるダメージでHit Stopするかは置いといて)

なので、少しだけ複雑です。
 
 
ですが、なにかわからないことがあれば
 
コメントして頂ければ、お答えします。もはやYoutubeで解説でもアリです。


 
まずAnyDamage のDamage Causer を変数に格納しましょう。
 
 

f:id:ifromjapan:20160930222002p:plain

 
 
 

僕の場合はApply Damageをする時に攻撃をしたキャラクターの情報をそこに設定しています。
 
剣でApply Damageしてもキャラクター 
 
銃で攻撃してもキャラクターです。
 

f:id:ifromjapan:20160930222019p:plain

 
 
そしてAny Damageはサーバー上でしか処理されないので、いちどマルチキャストを挟んで次のマクロを実行します。
*オフラインの場合はそのまま繋いで大丈夫です。

マクロの中身はこれです。
 
 

f:id:ifromjapan:20160930222029p:plain

 
 


赤で囲っているのはBluePrintInterfaceです。

 
一応簡単にBluePrintInterfaceについて説明しときます。
 
ご存じの方は読み飛ばしてください。
 
 
今回の場合は先程のDamageCauserに対して、

 

”君がしてきた攻撃はHitStopを使うのかい??使うのならば何秒間オイラはStopしたらいいんだい?”

 
 
 って事を聞いてます。

これだけ聞くと関数っぽいですよね。
 
 

攻撃をしてくる者が毎回絶対に決まっているのならば、毎回そいつの関数を呼び出せばいいけれども...

 

 
 
普通のゲームならばそれは、プレイヤーだったり敵だったり地面の火だったりして、
 
 

毎回同じアクターが攻撃してくるって事は無いですよね。

 
 
確かに、ダメージ毎に何が攻撃してきたのかを判断して
 
 
Castしてそいつの関数を使うこともできるのですが、非効率ですよね。
 
僕はめんどくさいです。
 
 


そこでBlueprintInterfaceです。

 
 

今回ならばAsk HitStopというインターフェイス

 

”プレイヤー”

 

”敵”

 

”地面の火”

 
 
 
に持たせてあげれば
 
毎回判断してキャストして呼び出す関数の代わりに、
 
 
そいつらが共通して持っている
 
”Ask HitStop"
 
を呼び出せば、そいつから情報を引き出せるってわけですね。
 
今回ならば、Bool とFloatです。
 
 
 
ちなみにAskHitstopの中身はそれぞれのブループリント内で自由にプログラムを組むことができます。
 
 
 
今回攻撃を行ったプレイヤーにもたせているAskHitStopの中身はこれです。
 
 
 

f:id:ifromjapan:20160930222152p:plain

 
 
 
 
先程自分の武器で設定したBoolをリターン用に一回格納してから
 
Boolの中身を空っぽにしています。

 
そして武器側で設定したHit Stop Time はそのまま返しています


攻撃を行うのがプレイヤーなのでまともに返していますが、

 
 


変速的な攻撃をする敵

 

同じ武器で同じ攻撃をした場合ならば

HitStopの時間をここでさらにいじったりすることも

 

BluePrintInterfaceなら可能です。

 
 
 
もし、わかりにくかったらコメント下さい。
先程のマクロに戻ります。
 
 
 

f:id:ifromjapan:20160930222052p:plain

 
 

ここで、受け取ったDo Hit Stopが Trueならば次のイベントを呼び出すって感じですね。
 
*もちろんオフラインの方はイベントを介さなくても大丈夫です。


 
呼び出されるイベントがこちらです。
こちらもマルチキャストです。
 
 

f:id:ifromjapan:20160930222126p:plain

 
 
 
ここでしている処理は攻撃が当たった瞬間に指定した時間だけ動きを止める処理です
 

先程、武器の方で行ったこれですね。
 
 
 

f:id:ifromjapan:20160930221939p:plain

 
 
 
 
 


なぜ今回はGameInstanceに一度飛ばしているかというと

 
 
 

Custom Time Dilation を 0.0に設定するとそのブループリント自体が止まってしまうからです。

 
その後のDelayやら、また1に戻す処理ができなくなってしまうので、あえて他のブループリントから処理をしています。
 
 
 

どのブループリントからしても良いのですが、GameInstanceならば基本的に誰でもアクセスできるのでそちらで行っています。
 
 
 
GameInstanceでやっている事は武器でやっていたことと同じですが、一応貼っておきます。
 
 

f:id:ifromjapan:20160930222238p:plain

 

f:id:ifromjapan:20160930222245p:plain

 
 
 
 
 
Instanceのイベントもマルチキャストでお願いします。
 
 
マクロにしているのは、ノードをいっぱい置くのがきらいだからです。
長くなりましたがこれでHit Stopが実装できました。
 

 

youtu.be

 

 

 


少しわかりにくいかもしれないのでお気軽にコメントしてください。

ありがとうございました。
 
 

 

blog.i-fromjapan.com