ぷちコン奮闘記!~タイマー処理・スコア表示~

今回作るゲームには、タイマーとキルカウント(敵を殺した数)がスコアとして表示される。

 

タイマー処理もキルカウント処理も、どちらもGameModeBaseに処理を組んでいる

 

まず、どのようにしてキル数のカウント処理をしてるのかを紹介しよう。

 

GameModeBase

自分が敵を殺したという通知が、「KillCount」インターフェースを経由して送られてくる。

敵が殺された時、「KillNumber」というInteger型の変数に殺した数を格納していく。

f:id:Free_Gamer:20180808003014p:plain

「KillCount」インターフェースは、前回の記事にも書いてあるはずなので、確認してほしい。

free-gamer.hatenablog.com

 

次にタイマー処理だ。

f:id:Free_Gamer:20180808002805p:plain

イベントTickを使用。

Delayで1秒おきに「TimerSecond」というInteger型の変数を1足している。

「TimerSecond」は、秒数を格納する為の変数だ。

デフォルト値は「0」

これで、1、2、3、4・・・というように1秒ずつタイマーが加算されていく。

だが、Delayとセット「TimerSecond」変数の間に、ブランチを挟んである。

これは、キル数(KillNumber)が目標キル数(KillGoalNumber)と同じになったら、Trueに処理が流れ、クリアーリザルトを表示するために、ウィジェットBPにインターフェースで処理を送っている。

そうすれば、タイマー処理も止まってくれる。

f:id:Free_Gamer:20180808003734p:plain

f:id:Free_Gamer:20180808004418p:plain

「TimerSecond」が「60」に到達したら、「〇分」経ったかを格納する為に、「TimerMinute」というInteger型の変数を1足している。

「TimerMinute」のデフォルト値は「0」

つまり、「TimerSecond」が60秒に達したら、1分経ったという事で「TimerMinute」に1足している。

という感じだ。

その後、また「0」から秒数をカウントしていく為に、TimerSecondを「0」にセット。

そしてまたタイマーを加算していく・・・のループだ。

 

f:id:Free_Gamer:20180808005605p:plain

 

UMGはこんな感じ。

f:id:Free_Gamer:20180808010223p:plain

 

実際にやってみた結果。

youtu.be

 

キル数が目標値に到達した時、つまりステージにいる敵を全員鏖(みなごろし)にした時、しっかりタイマーが止まっていた!

同時にキル数もカウントされていた!

 

それではまた!^^ノシ

 

 

 

 

ぷちコン奮闘記!~ぷちぷち小人をぶち殺していくゲーム!!!!~

さて!ぷちコンのテーマがようやく解禁されましたね!

テーマは「ぷち」

これまたよくわからないマニアックなテーマですw

 

このテーマに沿って、

 

「小人をぷちぷちぶち殺していくゲーム」!!!!!

 

を!作ることにした!

 

ステージはこの部屋丸ごと使った。

f:id:Free_Gamer:20180807001528p:plain

 

この部屋の中にうじゃうじゃいる小人たちを、左クリックでひたすら潰していくのだ。楽しいだろう??

 

今回は、「敵を殺す処理」を紹介する。

 

プレイヤー

「リアルなレンダリング」のアセットにデフォルトで入っているFPS_Character」をそのまま使っている。

 

コンポーネント

デフォルトだとカメラが入ってないので、カメラを追加。

f:id:Free_Gamer:20180807004424p:plain

「Z:90」の位置にカメラを設置した。

f:id:Free_Gamer:20180807004750p:plain

カメラの詳細パネル内の「CameraOption」項目にある赤枠で囲った部分にチェックを入れる。

チェックを入れないと、上下にカメラが動いてくれない。

f:id:Free_Gamer:20180807004550p:plain

 

イベントグラフ

f:id:Free_Gamer:20180807002931p:plain

カメラから5000の距離までトレースを飛ばす。

f:id:Free_Gamer:20180807003046p:plain

タグ判定でトレースが当たったアクターが指定したタグ持ちの敵かどうかを判定。

IsValidを入れないとエラーの嵐が起きる。

指定したタグ持ちのアクター(敵)にトレースがヒットした場合、Killインターフェースを経由して敵のBPに処理が送られる。

その後、殺した数、つまりスコア処理を行う為ゲームモードにも処理を送っている。

f:id:Free_Gamer:20180807003220p:plain

 

敵の名前は分かりやすく「Enemy」にした。

 

イベントグラフ

血のパーティクル・デカールをスポーン。

死んだときの音・声を再生し、最後に敵を破壊。

f:id:Free_Gamer:20180807003611p:plain

 

Enemyにトレースがヒットするように、Capsulecomponentのコリジョン「Visibility」を「ブロック」にしてある。

f:id:Free_Gamer:20180807004151p:plain

何故なら、トレースのコリジョンはVisibilityに設定してあるからだ。

f:id:Free_Gamer:20180807004239p:plain

 

youtu.be

 

しっかり殺害されていた!

 

これからぷちコンの進捗を上げていこうと思う!

 

それではまた!^^ノシ

 

 

GroupActor(グループアクター)って??

つい最近買ったアセットで、気になるものを見つけた。

f:id:Free_Gamer:20180805191721p:plain

赤枠で囲った部分。「GroupActor」「なんだこれ??」と。

 

そういうクラスがあるのかと思いきやそういうわけでもなく、

色々調べた結果・・・

 

「複数のアクターを『1つのアクター』としてまとめる機能」

 

だというのが分かった。

 

(例)

1つの壁を複数積み上げて作ったビルがあったとする。

X方向に2枚

Y方向に2枚

Z方向に5枚積み上げたシンプルなビルだ。

f:id:Free_Gamer:20180805194639p:plain

例えばこのビルを、ある位置に全部丸ごと動かしたい。となった時、

まあ恐らく「1枚ずつ壁をマメに移動させる」「壁を1枚ずつ複数選択して一気に運んでいく」かのどちらかだろう。

もちろんそれでも不可能ではないが、はっきり言って面倒だろう。

 

もし移動させる壁が更に多かったらどうなるだろうか。

1枚ずつマメにドラッグして移動させるのは考えたくもないし、

壁を複数選択して一気にドラッグで移動させたくても、複数選択する為に1枚ずつクリックして複数選択するのも面倒だ。

 

そういういった面倒を緩和してくれるのが「GroupActor」だ。

使用方法は簡単。

移動させたい壁を複数選択する。

f:id:Free_Gamer:20180805195844p:plain

ビューポート上、あるいはアウトライナ上で右クリックし、「グループ」を選択する。

 

ビューポート上の場合、指定のアクター(今回の場合だと壁)にカーソルを合わせた状態で右クリック。

f:id:Free_Gamer:20180805200448p:plain

アウトライナ上の場合、選択状態にしたアクターにカーソルを合わせた状態で右クリック。

f:id:Free_Gamer:20180805200252p:plain

 

「グループ」をクリックすると、以下の画像のように指定した壁が緑色の枠のようなもので囲われてるのが分かると思う。

f:id:Free_Gamer:20180805201855p:plain

指定したアクターを「1つのグループ」としてまとめた証拠だ。

 

アウトライナを確認すると、「GroupActor」というのが追加されてるはずだ。

f:id:Free_Gamer:20180805202248p:plain

この「GroupActor」を選択すれば、自動的に指定したアクターが複数選択される。

 

こうすれば、「ビルの位置を変更したい!」となった時も、「グループ」化してしまえば、簡単に指定した壁を複数一気に移動させることが可能なのだ。

 

ちなみに、この「グループ」化にはショートカットキーが存在する。

指定したアクターを複数選択し、「Ctrl+G」で「グループ」化が可能だ。

 

もちろん、「グループ」化を解除することだってできる。

「グループ」化したアクター上で右クリックし、「グループ化解除」を選択すればOKだ。

あるいは、ショートカットキー「Shift+G」でも解除可能だ。

f:id:Free_Gamer:20180805203704p:plain

 

youtu.be

 

この機能をうまく使えば、レベルデザインもなかなか楽になるかもしれない!(適当)

ぜひ活用していこう!

 

それではまた!^^ノシ

 

TPSシューティング奮闘記~ダッシュ(Sprint)処理!~

今回は、至ってシンプル。

通常移動速度からの全力ダッシュ処理だ。

 

ダッシュボタン(キー)・・・左Shiftキー、左スティック押し込み

 

f:id:Free_Gamer:20180803072847p:plain

Shiftキー押してない時は、通常移動速度(375のスピード)で移動するが、

Shiftキー押した時は、速度が「600」になり、通常よりも速い速度で移動が可能だ。

 

ダッシュボタン処理は、AxisMappingsで作成している。

f:id:Free_Gamer:20180803073655p:plain

 

 

但し、エイム中はダッシュ不可にしてある。

エイムボタンを押した時に、Bool値「Aim」がTrueになる為、Trueの先に繋がってる「MaxWalkSpeed375」に処理が走る。

つまり、エイム中は強制的に通常移動速度になるわけだ。

f:id:Free_Gamer:20180803072359p:plain

 

移動アニメーションは、ブレンドスぺースで作成している。

 

移動速度

0・・・Idle(待機)

225・・・Walk

375・・・Run(小走り)

600・・・Sprint(ダッシュ

f:id:Free_Gamer:20180803073120p:plain

 

実際にプレイしてみよう。

youtu.be

 

分かりづらかったら申し訳ないが、しっかり移動速度が変化している。

 

シューティングゲームではよくあるシステムだと思うので、ぜひ参考に。

 

それではまた!^^ノシ

TPSシューティング奮闘記~武器の変更~

前回の続き~!

 

前にも武器変更の記事書いたけど、今回は「銃」の切り替え!

free-gamer.hatenablog.com

 

~武器変更の為のボタン(キー)~

ピストルに変更・・・1キー、十字キー

ライフルに変更・・・2キー、十字キー

ショットガンに変更・・・3キー、十字キー

 

プレイヤーのイベントグラフ

f:id:Free_Gamer:20180801215200p:plain

 

 「CurrentWeapon」という変数は、「現在装備中の武器」が格納されてる。

※Current・・・現在 Weapon・・・武器

初期装備として「Pistol」を装備させてるので、「CurrentWeapon」には「Pistol(武器名NFP-16)」のBPが格納されてる。

DoOnceがあるのは、連打してアニメーションを何度も連発させない為。

 

f:id:Free_Gamer:20180801220144p:plain

例:Rifleに変更したい場合・・・

まず当然Rifleを持ってなきゃ変更できないので、IsValidでRifleがあるかどうかを判定してる。

もし持ってればIsValidはTrueになる。

そして、Rifleを所持していて尚且つ現在装備中の武器がライフル以外の物なら、NotEqualはTrueになる。

というわけだ。

 

つまり、Rifleに武器変更したい場合は・・・

 

・変更したい武器(Rifle)を所持。

・Rifle以外の武器を装備中

 

この2つの条件を満たしていれば武器の変更が可能になるのだ。

 

武器変更した際、どの武器に変更するかのEnum値をセットしている。

例えば、Rifleに武器変更する場合はEnum値が「Rifle」にセットされる。

f:id:Free_Gamer:20180801221202p:plain

※ 初期装備として「Pistol(NFP-16)」を装備させてる。

f:id:Free_Gamer:20180801220504p:plain

 

武器変更ボタン(キー)押した時、まず現在武器変更中という情報を格納する為に、「IsWeaponChange??」というBool値をTrueにセット。

そして、武器変更アニメーション(モンタージュ)を再生。

f:id:Free_Gamer:20180801222318p:plain

 

武器変更した際にセットしたEnum値は、ここで使われる。

「AttachWeapon」というカスタムイベントが呼ばれた時、実際に武器を変更する処理を行う。

各武器によってアタッチする場所が違うのでスイッチを使用している。

f:id:Free_Gamer:20180801221958p:plain

ちなみに、「AttachWeapon」カスタムイベントはAnimBPから呼び出されている。

f:id:Free_Gamer:20180801222645p:plain

この「ChangeWeapon」というのはモンタージュに設定したAnimNotify通知の事だ。

f:id:Free_Gamer:20180801222958p:plain

武器変更ボタンを押し、アニメーションが再生され、「ChangeWeapon」通知が来た時に、プレイヤーの武器変更処理を行う為のカスタムイベント「AttachWeapon」を呼び出す。

といった感じだ。

 

アタッチ処理はこんな感じ。

アタッチする場所は、すでに各武器に備わってる構造体「WeaponInfo」に格納されてるので、そのピンをただ繋げればいいだけ。(もっといい方法があるはずだけどなぁ・・・笑)

そして、アタッチ後変更した武器を現在装備中の武器として「CurrentWeapon」に格納。

f:id:Free_Gamer:20180801223431p:plain

 

最後に、武器ごとのアニメーション(IdleやWalkなど)を変更するために、トランディションルールBool値をセット。

ピストルに変更した際は、「EquipPistol」がTrue.「EquipRifle/ShotGun」がFalse。

ライフルかショットガンに変更した際は、「EquipPistol」をFalse。「EquipRifle/ShotGun」をTrue。

f:id:Free_Gamer:20180801224049p:plain

Animグラフ側

f:id:Free_Gamer:20180801224210p:plain

Pistol→Rifle/ShotGun

f:id:Free_Gamer:20180801224232p:plain

Rifle/ShotGun→Pistol

f:id:Free_Gamer:20180801224317p:plain

 

アタッチ処理が終わった後、「WeaponChangeEnd」カスタムイベントが呼び出される。呼び出された時、武器変更が終了したという事で「IsWeaponChange??」をFalseにする。

そして、DoOnceのResetに処理が流れ、もう一度武器変更が可能になる。

f:id:Free_Gamer:20180801224836p:plain

ちなみに、「WeaponChangeEnd」カスタムイベントはAnimBP側から呼び出されている。

f:id:Free_Gamer:20180801225230p:plain

「Reset」というのは、アニメーションモンタージュで設定したAnimNotify通知の事だ。

アニメーションの終わり辺りに設置している。

f:id:Free_Gamer:20180801225333p:plain

 

これでプレイしてみよう!

youtu.be

 

しっかり武器変更が行われている!

 

最後に実際の処理の流れも!見づらいようならごめん!笑

youtu.be

 

それではまた!^^ノシ

 

TPSシューティング奮闘記~武器の取得~

以前書いたような内容だと思うが、

free-gamer.hatenablog.com

free-gamer.hatenablog.com

まあ進捗という事でw

 

武器BPの作成

「WeaponMaster」という名の親BPを作成。

その子として、それぞれ

「Pistol」

「Rifle」

「ShotGun」

「SubMachinegun」

の子BPを作成した。

 

WeaponMaster

f:id:Free_Gamer:20180801180156p:plain

Widgetコンポーネントの設定

f:id:Free_Gamer:20180801180451p:plain

コンストラクションスクリプト

「WeaponInfo」という自作の構造体変数をセット。

f:id:Free_Gamer:20180801181550p:plain

イベントグラフ

f:id:Free_Gamer:20180801180533p:plain

f:id:Free_Gamer:20180801180802p:plain

WeaponMasterを継承した子BPそれぞれに、武器やウィジェットを設定していく。

(画像はWeaponMasterを継承した子BP「ShotGun」)

f:id:Free_Gamer:20180801180901p:plain

 

構造体・列挙体(Enum)の作成

 

武器の種類を格納するための列挙体「WeaponType」

f:id:Free_Gamer:20180801181330p:plain

武器の特徴を格納するための構造体「WeaponInfo」

f:id:Free_Gamer:20180801181407p:plain

 

武器取得処理

f:id:Free_Gamer:20180801181947p:plain

武器取得した時、このカスタムイベントが呼び出される。

f:id:Free_Gamer:20180801181958p:plain

 

参照したWeaponMasterから「WeaponInfo」構造体を参照。

「WeaponInfo」を分解。

「WeaponInfo」の中にある「WeaponType(自作した列挙体「WeaponType」)」で処理をスイッチ(切り替える)。

f:id:Free_Gamer:20180801182057p:plain

 

もっといい方法があるはずだが、まあ進捗なんでw

例えば、「Rifle」タイプの武器を取得したら、スイッチによって「Rifle」に繋がってる処理が行われる。

「Rifle」タイプの武器をスポーンし、プレイヤーにアタッチ。

その後、アタッチした武器のSphereコンポーネントを破壊。

これを破壊しないと、Sphereコンポーネントによって行われてるウィジェット表示とアウトライン表示が消えないから。

最後に、落ちていた武器を破壊。

f:id:Free_Gamer:20180801182312p:plain

 

ちなみに、初期装備として「Pistol」は最初っからプレイヤーにアタッチさせてる。

f:id:Free_Gamer:20180801183053p:plain

 

これでプレイしてみよう!

youtu.be

 

しっかり武器の取得が行われている!

 

ちょっと見づらいかもだが実際の処理の流れも。

youtu.be

 

ちょっとした参考までに!

 

それではまた!^^ノシ

 

 

 

TPSシューティング奮闘記~エイム処理~

エイム時の処理について僕がよく組んでいる処理を紹介する。

(何か以前にもエイム処理の記事書いたような気がするが気にしない気にしない)

 

エイム時の処理

f:id:Free_Gamer:20180730220829p:plain

エイムボタン押したら、「Aim」というBool値をTrueにセット。

放したら、Falseにセット。

f:id:Free_Gamer:20180730221143p:plain

この「Aim」変数は、エイムアニメーションに移行するためのトランディションルールBool値である。

f:id:Free_Gamer:20180730221446p:plain

 

エイム中(エイムボタン押した時)、平行移動させる。

OrientRotationToMovementのチェックを外し、UseControllerRotationYawにチェックを入れれば、常にカメラのほうに向く。

f:id:Free_Gamer:20180730221505p:plain

 

被写界深度処理(カメラのポストプロセスの強度)をセット。

エイム中は、被写界深度をON(1.0)。非エイム時は、被写界深度をOFF(0.0)にしている。

被写界深度処理は後程出てくる。

f:id:Free_Gamer:20180730221647p:plain

タイムラインでカメラの位置とプレイヤーとの距離を変更。

CameraBoom(SpringArm)の長さをグッと縮めて、キャラの肩越し視点になるようにする。

更に、CameraBoomのSocketOffsetの位置をプレイヤーの真横辺りにずらしている。

f:id:Free_Gamer:20180730221831p:plain

タイムラインは以下の通り。

タイムラインの長さは「0.1」

SpringLengthのタイムラインで、SpringArmの長さを300~100にしている。

SpringOffSetのタイムラインで、SpringArmのX,Zをプレイヤーの右方向にずらしている。

f:id:Free_Gamer:20180730222124p:plain

タイムライン処理の後、

Aim中(True)なら、SetTimerByFunctionNameへ。

非Aim時(False)なら、SetTimerByFunctionNameを止める処理へ。

SetTimerByFunctionNameのFunctionNameには、被写界深度処理を行うためのカスタムイベント「DepthOfField」を指定している。

「DepthOfField」イベントが呼び出されると、「DepthOfFieldSystem」という関数に処理が流れる。

f:id:Free_Gamer:20180730222339p:plain

「DepthOfFieldSystem」関数の中身。

f:id:Free_Gamer:20180730222700p:plain

プレイヤーカメラの位置から「5000」の距離までトレースを飛ばす。

f:id:Free_Gamer:20180730222756p:plain

ヒットした位置とプレイヤーカメラ位置の差を計算し、その結果を「FocalDistance」Float変数にセット。

カメラのポストプロセス変数を出し、「FocalDistance」変数をFocalDistanceピンに繋ぐ。

Apeture(F-stop)の値は「0.5」にした。

Methodは「CircleDOF」に。

この被写界深度処理については、以前も書いたのでそちらも参考に。

free-gamer.hatenablog.com

f:id:Free_Gamer:20180730222819p:plain

 

これでプレイしてみよう!

youtu.be

 

エイム中は、カメラがグッとプレイヤーに近づき、プレイヤーの肩越し辺りにカメラが来ていた!

更に、エイム中は被写界深度処理がしっかり行われていた!

その証拠に、エイム中は近くのものがくっきりしたりぼやけていたりしていた!

 

TPSシューティングを作る際は、ぜひとも参考にしてみてほしい。

もちろん不満ならいくらでも改造して構わない。

 

それではまた!^^ノシ