スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

UE4ゲーム制作入門十五日目

一人UE4ゲーム制作入門アドベントカレンダー十五日目です。

Touchが来たことに加えて、お仕事の雲行きが怪しくなってきたので割りと進捗が少ないかもしれません・・・。
それでも完走はしますよ!(完成するとは言ってない

昨日作った案山子状態のボスを実装していきたかったですが、時間が気づいたら日をまたいでいて、中身を全然考えてなかったのでガワだけ用意するだけです。

とりあえずこんな感じで、行動を3つ用意しました。アニメーションがおもったよりなかったので、こんな感じになってしまいました。
遷移に関しては、思いつかなかったので状態管理用の列挙型を用意して、攻撃終わったらIdleにもどって、Idleが終わったらプレイヤーとの位置で色々変えていこうかなって思っています。できるかはわかりません。現時点では2つで試してうまく行って、ゲームが出来上がったら対応します。
ABP_Boss.png

各アニメーションには通知を入れています。この通知イベントで当たり判定やらを操作しようと画策しています。
アニメーション通知

通知イベントで実行するための関数をBP_BossAIを作って、全部用意しました。この中に当たり判定の操作などを用意します。
AI.png

スケルタルメッシュの右手にソケットを作って、当たり判定用のBP_Weaponというブループリントクラスを作り、BeginPlayで作成+ソケットにアタッチしています。できたら、武器のメッシュだったりエフェクトをここに追加して色々できたらなぁって妄想してます。
あとは、無敵時間をつくれるようにinvicibleStart、End関数を作っています。
BP_Boss_201612150038121d1.png

急いで書いたので多分漏れもありますが、明日の僕がなんとかすることでしょう。

UE4ゲーム制作入門十四日目

一人UE4ゲーム制作入門アドベントカレンダー十四日目です。

やっぱりステージ遷移のロジックはどこかにまとめておいたほうがいいので作り直します。あとボス。

ボスマップを作る


まずは遷移先を揃えておいたほうがいいので、新しくレベルを作り、BossMapと名前をつけましょう。
見た目は今は気にしないので適当に作ります。
ボスマップ

ボスマップのレベルブループリントにも処理を追加します。プレイヤーの位置をボスマップのPlayerStartの位置へとテレポートさせています。
ボスマップのレベルブループリント

作ったら、パーシスタントレベルのサブレベルにしておいてください。

ボスを作る


さっきのスクショに写ってましたが、ボスを作ります。BP_Enemyから子クラスを作り、BP_Enemy_Bossと名前をつけます。
スケルタルメッシュには、InfinityBladeのSK_Enemy_FrostGiant_Captainを使います。
BP_Boss.png

処理はこれだけ。死んだらリザルトへ。実際に動くのは明日以降になります。
Bossの実装部分

管理用の列挙体を準備する


ステージを作成していきましょう。
まずは、ステージの管理用に列挙体を用意します。コンテンツブラウザ上で右クリックして、Blueprintsから列挙体(Enumeration)を選びます。
列挙体の名前はEN_Stageとしておきます。作った列挙体をダブルクリックで開き、スクショのように値を設定します。
ステージ管理用列挙体

ステージ遷移をゲームモードで行う


基本的に常にレベル上に存在しているアクターだと思うので、ここに実装しておきます。

ChangeStage
基本的にはこの関数を外から呼ぶことになります。列挙体の値で新しくロードするレベルと消すレベルの名前を、実装した関数のGetLevelNameから変数に設定しています。
そして最後にカスタムイベントで実際にレベルを移すInitStageを実行しています。
ChangeStage.png

GetLevelName
列挙体の名前をStringに変換して、からName変数にして返しています。
GetLevelName.png

InitStage
関数の中ではLoadStreamLevelとUnLoadStreamLevelは呼び出せないのでカスタムイベントで遷移を行います。
UnLoadLevelNameはNONEの場合、UnLoad処理を飛ばします。Loadの方はそもそもLoadしない状況にはならないので、ただLoadしています。
InitStage.png

遷移を行っていた部分を置き換える


パーシスタントレベルブループリントの変更点
ゲーム開始時にタイトルを読み込んでいるのでそこを変更します。UnLoadするレベルは存在しないので引数UnLoadにはNONEを設定します。
パーシスタントレベル

WG_Titleの変更点
タイトルからゲームレベルへの移行部分。
WG_Titleの変更点

BP_Playerの変更点
死亡時にリザルトを呼び出しています。
BP_Playerの変更点

ボスマップへの遷移をつくる


ボスマップへの移動はこのゲームではテレポートポイント的なのを用意します。ブループリントクラスを新しくActorを親クラスとして作ります。名前はBP_MoveStreamingMapActorです。長いし汚い

オーバーラップのコリジョンを持つだけのアクターです。とりあえずですので、後ほどパーティクルなりメッシュなりで見た目を扉かテレポートポイントっぽいなにかにします。
BP_MoveStreamingMapActor.png

移動部分。ボックスコリジョンに入ったらレベルを読み込みます。ボスマップには読み込まれた瞬間にプレイヤーをボスマップの初期位置へと移動させる処理を持っているので、これでボスマップへと自動でワープします。
BP_Move以下略のイベントグラフ

ボスマップをサブレベルにし、ワープポイントのアクターを適当な場所に配置してきちんとMainをUnLoad、BossMapをLoadに設定します。
きちんとボスの前に移動したあと、ボスに弾を当ててリザルト画面がでたらオッケーです。

UE4ゲーム制作入門十三日目

一人UE4ゲーム制作入門アドベントカレンダー十三日目です。

昨日つくった敵の親クラスを使って、新しい敵を作ります。新しくEnemyクラスの下にRoboフォルダを作ります。Bearフォルダも作ってなかった気がするので作って、入れておきましょう。

BP_Roboを作る


親クラスにしたいブループリントクラスを右クリックし、子クラスを作るを選択します。
子クラス作成

できたブループリントクラスには、BP_Roboという名前をつけておきます。

このBP_Roboクラスは、ほぼすべての処理をEnemyに書かれてるので実装するのは、オーバーライドした関数Attack以外にありません。
BP_Roboのイベントグラフ

敵の弾を作る


Attackで飛ばす弾を作ります。といっても、プレイヤーフォルダに有るBP_Shotoを複製、またはコピーアンドペーストし、Roboフォルダに入れます。
同じ色だとわかりにくいので違う色のマテリアルを作って設定します。
ShotE.png


BP_RoboAIを作る


AIコントローラとビヘイビアツリーも新しく作り直します。今回のロボは、配置した位置から移動しません。プレイヤーを見つけたら、そちらに向き、一定間隔で弾を撃ち出す固定砲台です。
AIコントローラから行きます。ブループリントクラスから、AIコントローラを作ったら開きます。BeginPlayでブラックボートとビヘイビアツリーを設定します。この2つは後で作ります。
BP_RoboAI.png

そして、プレイヤーを探すSearchPlayr関数です。サービスで似たようなものを作りましたが、必要のない処理もあって動かなかったため、こっちに新しく作り直しました。
処理としては単純に、合わせて作った変数SearchRangeの範囲内にプレイヤーが入ってるかどうかの結果を返しています。trueだろうがfalseだろうがPlayerPawnを返します。このあたりはサービスのSearchPlayerと変わりません。
SearchRangeの値はここでは800に設定しています。
BP_RoboAI2

BT_RoboとBB_Roboをつくる


クマのときと同じように、ビヘイビアツリーを作ります。その後、新規ブラックボードを作成し、それをルートノードからアタッチします。
まずはビヘイビアツリーの全体です。大体クマと一緒ですが、いくつか変えてあります。
攻撃側と索敵側で分けて説明します。
RoboAIのビヘイビアツリー

攻撃


索敵側で、プレイヤーを見つけられていたらこちらに回ってきます。
LookAtTargetタスクではセットされたターゲットアクターを向き続けます。
BP_RoboAIのLookAtRotationタスク

Shotタスクでは、BP_EnemyのAttackクラスを実行しています。Shotと銘打ってますが、BP_Enemyの子クラス全部で使えそうですね。今気づきました。
そして、実行後は5秒間のクールタイムです。初期値が5秒なだけなので、好きな値にしてもいいですが、0にしたら大変なことになるのでやめておいたほうが身のためです。
BP_RoboAIのShotタスク


索敵


男らしくタスクは一つだけ。プレイヤーが索敵範囲内かどうかを調べるそれだけです。AIに実装したSearchPlayerでtrueなら一緒に帰ってきたPlayerのインスタンスをブラックボードのTargetPawnに与えます。
範囲外であるfalseなら空っぽにしてやり、攻撃側の実行がされないようにします。
BP_RoboAIのSearchPlayerタスク

完成


これでワールドに配置して、索敵範囲内にプレイヤーが入ると、こちらを向いて弾を撃ってくれば成功です。

UE4ゲーム制作入門十二日目

一人UE4ゲーム制作入門アドベントカレンダー十二日目です。

二日に渡る関西UE4ゲームジャムお疲れ様でした。色々と学ぶものと反省点が多かったですが、とても楽しかったです。一緒に組んだEチームの皆さんありがとうございました。

今日は、他の種類の敵を作るために敵のベースクラスを作ります。

BP_Enemyをベースクラスとする


まず、今まで作っていたBP_Enemyのコピーを取ります。

複製したクマBP_EnemyをBP_Bearに名前を、親クラスをBP_Enemyに変更しましょう。その際、継承した先に同じ変数や関数があるために、後ろに数字の付いた名前になったり、エラーをはいたりすると思うので、全部消します。
しかし、継承した変数が見えないのは利用しづらいので、表示するように変更します。
継承した変数を表示
また、後述しますが、親クラスには子クラスで別々の処理をさせたい場合、関数の宣言だけをしておくことになります。その実装をするには、このオーバーライドというのを選ぶと、基本的にはイベントノードがイベントグラフに、返り値があればFunctionsのところに追加されます。
オーバーライド

BP_BearではDestroyFuncとAttackをオーバーライドして実装します。
中身はコピペなので、BP_Enemyから持ってきてください。
BP_Bearのオーバーライド死亡
BP_Bearのオーバーライド攻撃
親クラスである、BP_Enemyでは先程行ったとおり、中身を空っぽ同然のものにします。Meshコンポーネントのメッシュ、関数のAttack、DestroyFuncの中身を全部まっさらにして、関数は宣言だけした状態にしておきます。小クラスとなった各敵ごとに実装していくことになります。
BP_Enemyのイベントグラフ
BP_EnemyのDestroyFunc
BP_EnemyのAttack

StopAIはStopLogicを使って止めるように変更しておきます。AIコントローラに無理に、停止用関数を実装しなくてもとめられるようになります。
BP_EnemyのStopAI

今まで使っていたBP_EnemyAIControllerはBP_BearAIに名前を変えます。Controllerを名前から抜いたのは多分その時の気分です。記憶が曖昧なのですみません。
必要のなくなったStopAI関数を消し、なぜかステージ遷移を行うようになってからバグる様になったBeginPlayにあった初期化関係にDelayをかましてやって動かすようにしました。こうしないと、どうもコントロールしているポーンにアクセスできなくなっていたのです。
BP_BearAIのイベントグラフ

今回はこんなところ。次回、次の敵を作ります。

UE4ゲーム制作入門十一日目

一人UE4ゲーム制作入門アドベントカレンダー十一日目です。

更に、土曜日は関西UE4GameJamの1日目でした。

今回は遷移を作ってみました。なお、本人わけわかんなくなってすごい無駄なことやってる気がするので、どうしようかなって思ってます。

パーシスタントレベルを用意して、その下にタイトルや実際のステージ、リザルトを配置します。
レベル配置

パーシスタントレベルは一番初めに読み込まれる際にタイトルを自動でロードするようにしてます。
パーシスタントレベルブループリント

タイトルレベルは、開始時にBP_PlayerのメッシュのVisibleを消したりするために実装したInvalidPlayer関数を実行した後、タイトルウィジェットを作成して、UI以外に入力がとられないようにしました。
タイトルレベルブループリント

InvalidPlayerは、プレイヤーのMeshを見えなくして、もしRifleが生成されていたら破棄する処理になっています。
PlayerのInvalidPlayer関数

タイトルウィジェットであるWG_Titleはゲームタイトルと開始判定用のボタンです。背景画像とか時間があったらWindowsPaintの本気を見せようと思いましたが、無理でした・・・。あと。アニメーションも後でつけます。今は余裕がありませんw
WG_Title.png

開始ボタンが押された時の処理は、今まで作ってきていたMainレベルをストリーミングロードし、このウィジェットを画面から外して、Titleレベルを消して、入力をゲームのみにしています。
WG_Titleのボタン押したときの処理

次にメインレベルのレベルブループリントです。まず、PlayerStartの位置にすでに生成されているBP_Playerを移動させます。
そのあと、消えているMeshやRifleを見えるようにするInitGame関数を走らせています。
MainLevelブループリント

InitGame関数の中身ですが、先ほどのInvalidPlayerの逆のようなことをやっています。
BP_PlayerのInitGame関数

リザルト画面に遷移するのは、現段階ではプレイヤーが死んだときくらいなので、プレイヤーの死亡処理の後ろにリザルト画面をストリーミングロードしています。
Playerダメージ処理

ロードされたリザルト画面はリザルトウィジェットであるWG_Resultを適用します。その前に、何かしらのウィジェットが適用されていた場合を考えて、すべてのウィジェットを外しています。
Resultレベルブループリント

WG_Resultは単純にGameEndという文字を表示しているだけです。
WG_Result.png

WG_Resultは特に操作は今のところしないので、表示されて一定時間たったらパーシスタントレベルをOpenLevelしてリセットしています。
WG_Resultのイベントグラフ

遷移の際にいろいろなところから起きているので、遷移イベントを適当なマネージャアクターを作ってそこで管理すべきかなぁと思いました。

UE4ゲーム制作入門十日目

一人UE4ゲーム制作入門アドベントカレンダー十日目です。

今日は昨日のAIを賢くしていきます。今のAIはそもそも見えない位置からでも、どんなに離れていてもこちらを補足して、一心不乱に突っ込んでくるバーサーカークマです。
確かに、そういうのもいなくはないですが、今回のように狭いステージでそのようなAIしかいないのはあまりよろしくはありません。

ビヘイビアツリーの中身


今回作るビヘイビアツリーの全体図から行きます。中身は一新しました。前回の作ったタスクは、結局MoveToに置き換えています。
本当はもうちょっとこういうのが作りたいっていうのがあって色々試していたんですが、うまいこと動かず、時間もないので今回は極め本のものを参考に簡略化したものを使っています。
それでは一つ一つを簡単に説明していきます。コンポジットやMoveToは省略させてもらいます。
極め本簡略式ビヘイビアツリー

デコレーター


①のところには、青い3つのノードがコンポジットの中に入っています。これはデコレーターと言って、条件式を満たしていれば、このツリーを実行するというif文的なのを付与してくれます。
今回の例でいきますと、上から
・ブラックボードのTargetPawn変数の値がセットされていてるか。
・このツリーが実行されて5秒以上立ったら強制的にFalseを返す。
・TimeLimitのあとに1秒クールダウン時間をとる
になります。

サービス


サービスはコンポジットの実行中に、定義された頻度で実行されます。ブラックボードの値などを頻繁に変えたいときなどに使うそうです。(ほぼ初めて使った
今回のこのサービスは、極め本のと差別化を図るべく中身は変えてあり、視線レイが当たったときではなく、一定範囲内にプレイヤーが入ったら捕捉して追ってくるようにしています。
紛らわしい名前で申し訳ありませんが、isMoveという捕捉中にtrueになるbool変数を操作しています。これにより、捕捉中は敵が攻撃していることになります。
サーチプレイヤーサービス


AIコントローラに実際の索敵処理が書いてあります。
SearchPlayerの中身


タスク


左のツリーのMoveToはセットされたターゲット、このビヘイビアツリーではPlayerしかセットしてないので、Playerを追うためのタスクになっています。

極め本のとほぼほぼ中身が同じなので、スクショ上げていいかよくわからないので、説明だけしていきます。
GetPatrolLocation
巡回移動する先のターゲットポイントを配列として持っていて、その中から指定されたIndexのLocationを取り出しています。

二つ目のMoveToは実際に指定された移動先へと移動しています。このツリーはSequenceなので、実際に移動先につくまではFalseが返って、後ろの2つのタスクを飛ばすことができます。

WaitBlackboadTimeは指定したブラックボードのfloat変数の値だけ停止します。

PopPatrolLocation
巡回移動先の配列のインデックスを変更します。剰余で計算しているため、最大数になったときには自動的に0にもどり、始めの巡回先へと移動するようになっています。

攻撃処理


攻撃はisMoveがTrueの間は判定を出すようにしています。
攻撃処理

呼び出してるAttack関数に実際にダメージを与える処理を書いています。レイにぶつかったらダメージを与えるというものになっています。これも同じな気がするのでスクショ省略。
ただ、PlayerのCapsuleComponentはコリジョンがVisibllityはヒットしないようになっているので、専用のコリジョンチャンネルを作るか、Cameraにするか、CapsuleComponentのコリジョンを変えましょう。
僕は後で直す(予定)にして、Cameraでとりあえずやっています。

プレイヤーのダメージ処理


ほぼほぼ、BP_Enemyのものと変わりません。ダメージを貰ったら、持っているステータス構造体のHPを減らして、ゼロ以下になったら死亡処理を行います。

できた





AIはきちんとしたものは作ったことがないため、こんな形になりました。誰か教えてください。

とりあえず、極め本とか公式のビヘイビアツリーの組み方を見つつ、この説明通りに組めたら、配置したターゲットポイントを巡回しつつ、索敵範囲内へとプレイヤーが入った場合、突進する敵が見れると思います。
一応記事を書いてる途中に、なんとなく組みたかったAIの実装方法を思いついたので、一通りゲームが完成してうまく動いたら番外編であげるかも?


おまけ


迷走しまくったタスクの山(大体が使えない
タスクの残骸

UE4ゲーム制作入門九日目

一人UE4ゲーム制作入門アドベントカレンダー九日目です。

今日はAIを作ります。せっかくプレイヤーの死亡アニメーションを作ったのに自殺しかできないのは哀しいですからね。

クマAI作成開始


まずはAIを作るために必要なビヘイビアツリーを用意します。
ビヘイビアツリーは、タスクを組み合わせて、実際のAIの処理を実装するものです。
名前はBT_Bearです。
ビヘイビアツリー作成

今の動きを移植してみる


まずは自分に向かってくる敵を作ってみましょう。まずはBT_Bearを開きます。
①開いたら、ブラックボートを作ります。
ブラックボードは、タスク間、もしくは同じブラックボードを持っているアクター間で同じ変数を共有するためのものです。
名前はBB_Bearです。
②ビヘイビアツリーに戻って、先程のブラックボードをセットします。
セットできたら、ROOTの下側部分の濃い黒い部分からドラッグをします。するとコンポジットを選ぶことができます。
コンポジットは、タスクの流れを制御するためのノードです。
今回はSequenceを選びましょう。
③プレイヤーに向かって移動するという命令を作ります。NewTaskから新しくタスクを作ります。
すると、作られたタスクのウィンドウが自動で開くので、中身を実装・・・する前に、名前をコンテンツブラウザから変更します。
BTask_MoveToPlayerという名前にしましょう。
ビヘイビアツリーの中身

改めて、タスクの中身を実装していきます。まず、Event Receive ExecuteAIを配置します。このノードはこのタスクがAIで使われている際のスタートポイントになります。
次に変数を作りましょう。名前はTargetです。
型はBlackboadKeySelectorというブラックボードの変数を参照することのできる変数です。Publicにしておくことで、ビヘイビアツリー上で使用するブラックボードの変数をBlackboadKeySelectorに割り当てることができます。
使用方法は赤丸で囲ってあるとおり、getして、ノードを伸ばすとGet(Set)Blackboad value * みたいなノードがいっぱい出てくると思います。今回はActorの情報を参照したいのでGet Blackboad Value as Actor を呼び出します。
SimpleMoveToActorで移動させ、FinishExecuteをtrueで返して終わります。Trueを返さない場合、AIがうまく動かずに止まります。

実はすでに用意されているタスクのMoveToでもよかったりします。
タスクの中身

ブラックボードに変数を設定しましょう。NewKeyからObject型の変数を作ります。名前はTargetです。
その次に、右側の詳細画面でKeyTypeが小さくなっているのですべて開きます。するとBaseClassを選べるので、Actorを選びます。
Blackboadの中身

あとはAIコントローラでビヘイビアツリーとブラックボードを走らせれば、AIが動きます。
その際、もともとテスト用に使っていたMoveToActorはTickから外します。この画像では残っていますが、消しても全然構いません。
AIコントローラ

やってみた





うまく動かない場合はNavMeshVolumeがうまく動いてない可能性があります。きちんとステージ全体が範囲内に入っているか、Pボタンをエディタ上で押して緑色になるかどうかを確認し、ビルドを通して再度Pボタンを押して確認してみてください。

明日はこのAIをよりゲーム向きに改良します。

UE4ゲーム制作入門八日目

一人UE4ゲーム制作入門アドベントカレンダー八日目です。

今日はプレイヤーが死ぬ処理を作りましょう。

死亡アニメーションをつくる


クマとかは死亡時のアニメーションを初めから持っていますが、グレーマンは持っていません(僕の把握してる限り
なので、今回は物理アセットアニメーションを使って、死亡時の動きを作ります。

グレーマンは初めから物理アセットアニメーションを持っているので、今回はそれを使います。あと、クマはとりあえずは邪魔なので消しておきましょう。

ステージをスタティックメッシュにする


ラグドールにすると、ジオメトリのままだとすり抜けるので、地面をスタティックメッシュにして、コリジョンを適用します。
この時、僕の作ったマップではコリジョンの適用が大変なことになって色々修正する羽目になったので皆さんも気をつけてください。
やり方は、Ctrlキーを押しながらクリックして複数選択した後スタティックメッシュ化して、その後、メッシュのウィンドウでコリジョンを適用します。単純な形ならBox、複雑ならば上のCollisionタブからAddConvexCollisionを選びます。すると右下にConvexDecompositionタブが出て来るので、そこの値をいじってApplyすることで複雑な形のCollisionを作ることができます。
Accuracyは正確さで、MaxHullVertsはコリジョン メッシュが持つ頂点数を増加、減少させます。これらを増やすと、より複雑なコリジョンメッシュになります。
作った後に気づいたことですが、できるだけ単純な形で分割してスタティックメッシュ化しましょう。あとで無理やりコリジョンメッシュを移動させたり、大きくしたりして対応する必要がでて、とても面倒です。
コリジョン2
コリジョン3
コリジョン4
床のコリジョン

物理アセットアニメーションを再生する


ステージが終わったら、本題の物理アセットを適用します。まず、きちんと物理アセットが適用されているかを確認します。僕と同じマネキンを使っていたら初めから適用されているはずですが、確認はしておきましょう。
スケルタルメッシュのこの画面で左の詳細ウィンドウのスクロールを一番下に行ったところにある赤丸の部分を確認しましょう。
物理アセットの確認

今回クマには攻撃やダメージ処理はつけていませんし、ちゃんと動くかどうかだけ見たいので入力があったら、物理を起動させる形にしました。
ラグドール起動

実際に物理アセットを有効にしている中身はこれです。物理シミュレーションを起動してから、メッシュのコリジョンをラグドール用に切り替えます。これをしないと、メッシュが床をすり抜けます。
その後に、CharacterMovementを無効化してます。倒れたのに移動してたらおかしいですしね。ちなみに、無効化しなければメッシュを置いてけぼりにしてBP_Playerが動き続けます。
ラグドールを有効化

確認してみる





無事動きました。

UE4ゲーム制作入門七日目

一人UE4ゲーム制作入門アドベントカレンダー七日目です。

今回は敵の死亡処理を作ります。

ステータスの作成


まずは、ステータスを作りましょう。今回は共通のステータスなので、自分の名前フォルダかコンテンツフォルダの直下に右クリックから、ブループリントカテゴリの中にある構造体を選んで作成します。
名前はST_Statusにします。
構造体の作り方

ST_Statusの中身はこれです。float変数が一つというアレな状態ですが、今後共通するステータスがある場合、ここに追加していくことになります。
ST_Statusの中身

ステータス更新用のマクロライブラリの作成


次に、このステータス構造体の中身を更新するためのマクロ群をまとめておくための、ブループリントマクロライブラリーを作ります。
使い方があってるかどうか、よくわかってないので誰か指摘ください。
コンテンツブラウザ上の自分の名前フォルダかコンテントフォルダで右クリックして、ブループリントカテゴリのブループリントマクロライブラリーを選んで作成します。
名前は、BPM_Statusです。
BlueprintMacroLibraryを作る

この中に2つマクロを作ります。
一つ目が、ダメージ処理です。名前はCalcDamageです。
ST_Statusをもらってきて、その中身のHealthだけを更新して構造体にして戻しています。もう一つのfloatは計算後の体力を返すことで、死亡判定に使えるようにしています。
CalcHealth.png

もう一つが、死亡判定です。単純に0以下なら死亡扱いになります。
名前はCheckDeathです。
CheckDeath.png

変数と関数の名前付けにもうちょいセンスが欲しいところ。

敵側のダメージ処理の実装


次は敵にダメージ処理を実装します。AnyDamageという、ApplyDamageでダメージを与えられたときに発生するイベントから、HPを更新しています。そして、HPが0以下になった場合は死亡処理を行うようにしています。
敵ダメージ処理

死亡時に呼んでいるDestroyFuncの中身はこんな感じです。死亡時アニメーションをスタートさせています。
DestroyFunc.png

アニメーションも、isDeathがtrueなら死亡アニメーションへ遷移するようにしています。赤丸で囲っているのが、先程のBP_Enemyから呼び出している、isDeath変数をtrueにする関数です。
Deathアニメーション終了時イベントを実装する1

アニメーション終了時のイベント通知を設定します。上のタイムラインで右クリックするとAdd Notify...>New Notifyで名前を入力すると、イベント通知が設定できます。僕の方の名前はEndDeathAnimです。
作ったイベント通知はドラッグして好きな時間に設定できるので、今回は一番うしろに設定します。
死亡アニメーションを設定する

こっちは先程作ったアニメーションが再生し終わったときに発生するイベントの実装です。当然死亡アニメーションが再生しきったら消えてもらいます。
Deathアニメーション終了時イベントを実装する2

弾のダメージを与える処理の実装


次に弾の方をなんとかします。まずStaticMeshのコリジョンをNoCollisionに変更します。これをなくさないとクマが地平の彼方へ飛んでいきます。
ShereCollisionはOverlapイベントで当たり判定を取ります。そして、当たったアクターに対してApplyDamageで、fDamage変数の値分ダメージを与えます。
ApplyDamageはクマの方に実装したAnyDamageに対してダメージを渡します。
そして、ダメージを与え終わったら消します。消さなければ、延々とダメージを与え続ける理不尽武装になります。ある意味面白いのでそっちが良ければDestroyActorを消してみるのもいいかもしれませんね。(今はHP1しかないから特に意味ないけど
ダメージを与える

当ててみる





こんな感じになってたらオッケーです。

UE4ゲーム制作入門六日目

一人UE4ゲーム制作入門アドベントカレンダー六日目です。

今日は昨日放り投げた、攻撃の続きを実装していきます。
そして、一番最初に言ってしまうと、前回のプレイヤーのアニメーションほぼ全とっかえになります。
本来はBlendさせて上半身だけ銃構えるのにして、楽をしようと思っていたのですが、逆にめんどくさいことになったので、もともとあるやつをまたパクります。

アニメーションとかモデルのアセットの準備


言い訳も終わったところで始めていきましょう。まずは、攻撃アニメーションを持ってきます。マーケットプレイスからAnimationStarterPackを持ってきます。サムネイルがグレーマンがピストル構えてるやつになります。

次にライフルのモデルを持ってきます。ShooterGameというラーニングにあるサンプルプロジェクトから、Rifleというスケルタルメッシュを持ってきます。

アニメーションのリターゲット


今回の準備は整いました。まずは、AnimationStarterPackからRifleと名前のついたアニメーションを僕らが使っている方のグレーマンに適用します。AnimationStarterPackに入っている、グレーマンにすり替えてもいいのですが、アニメーションリターゲットの説明に使えるのでやります。

まずはコンテンツブラウザの検索からRifleのアニメーションを探します。検索結果がこんな感じになったら全部を選択して、右クリックしてアニメーションリターゲットします。
右下でリターゲットした後のアニメーションをエクスポートする先を選びます。
①と書かれたところのチェックを外さないとリ・ターゲットするスケルトンを互換性がないスケルトンを表示させて適用させることができません。
チェックを外した後②の部分にUE4とうつといま使ってるグレーマンのスケルトンが選べます。
6_201612042106569b4.png
6_201612042106569b4.png
7_201612042106584cc.png

他にもBS_JogとかAim_Space_Hipとかもリターゲットしておきます。

ABP_Playerの編集


終わったらアニメーションブループリントを編集していきます。いじくりすぎて記憶があやふやになってしまっているのですが、Idle/RunからIdleにステートの名前を変えて、アニメーションをIdle_Rifle_Hipに変えて、新しくRunステートを作って、BS_Jogをアニメーションにします。見てもらったらわかると思いますが、BS_Jogはブレンドスペースです。
8_2016120422141981b.png

speedとDirectionのfloat変数をなければ、作ってつなげます。速さと向きを制御します。
9_20161204221905762.png

待機と移動アニメーションを分離させたことによって遷移部分を多少変えなければなりません。

まず、IdleとRunの間に遷移条件をつけます。
Idle > Run : speed > 10
Run < Idle : speed <= 10

IdleとJump関連
Idle > JumpStart : isInAir?がtrue
Idle < JumpEnd : GetRelevantAnimTimeRemaining() < 0.2 且つ speed <= 10

RunとJump関連
Idle > JumpStart : isInAir?がtrue
Idle < JumpEnd : GetRelevantAnimTimeRemaining() < 0.2 且つ speed > 10

です。ライフルを抱えたジャンプモーションもありますが、今のやつでなかなかおもしろいのでそのままにしておきます。

次にAimOffsetを作ります。しかし細かい説明はすべてすっ飛ばします。公式のを参考にしてください。
公式:AimOffsetを作成する
私が行った簡単な流れだけは説明しておくと、
・PlayerのAnimationフォルダにAimOffsetフォルダを作成
・Aim_Space_Hipのアニメーションをリターゲットし、AimOffsetフォルダへ
・Aim_Space_Hipアニメーションから各9方向への向きのポーズを作成
・PlayerAimOffsetという名前のAimOffsetを作成
・先ほど作ったAimOffsetのパラメータを調整し、先程作ったポーズを適用
こんな流れです。細かいパラメータの値や方法は先程の公式に書いてあります。バージョンが古いですが、特に操作は変わってないので問題ありません。

AimOffsetが完成したら、ABP_Playerで実際に動かせるようにしましょう。

大体公式の説明と同じですが、微妙に変えた部分があるのでその辺だけ説明しておきます。

公式ではしゃがみとか線形補間で滑らかにしていますが、こっちではその辺簡略化してます。
GetAimOffsetという新しく作った関数の戻り値の回転のYawとPitchを新しく作った2つのfloat変数にセットしています。この2つで、AimOffsetの向きを制御します。
ABP_Playerのイベントグラフ詳細

GetAimOffsetはこんな感じです。コントローラとアクタの回転の差分を取ってます。多分すごい無駄です。この辺から僕の頭の悪さがにじみ出始めます。
GetAimOffsetの中身

ライフルをもたせる


次にライフルをもたせましょう。グレーマンのスケルタルメッシュにアタッチする先のソケットを設定します。
ソケット名から位置とか回転とか取れて、アタッチしたアクターがアニメーションに追随してくれるようになるのでとても便利です。公式をみて覚えましょう。
ちなみに僕は全然わからないです。
weaponsocketの

次に、ライフル自体を作りましょう。Playerフォルダの中にWeaponフォルダを作り、その中にActorクラスを親としたBP_Rifleブループリントクラスを作ります。
ウィンドウを開いて、コンポーネントルートにSceneコンポーネントを配置し、スケルタルメッシュとArrowコンポーネントをその下に追加します。スケルタルメッシュにはSooterGameから持ってきたRifleを設定し、-90度回転させます。
Arrowコンポーネントは、銃口に配置します。
BP_Rifle.png

コンポーネントの設定が完了したら、GetShotPos関数を作ります。中身はこんな感じです。
昨日作った弾は前方向に延々と飛んで行くので、自分の見ている方向へ向かせてやらねばなりません。なおかつ、銃口から出ていないとおかしいので先程作ったArrowコンポーネントの位置から生成する位置を設定しています。
GetShotPosのなかみ

戻って、BP_PlayerのBeginPlayにこれを作ります。ライフルを、プレイヤーが生成された瞬間に生成してから、先程作ったソケットにアタッチしています。あと、RifleのGetShotPosを呼び出しやすいように、生成したアクターを変数に格納しています。
ライフルのアタッチ

AttachWeaponの中身はこんな感じです。単純にしてます。
Attatch_Weapon.png

弾を撃てるようにする


ついに、弾を発射できるようにします。

まずは入力でShotを作ります。プロジェクト設定のインプットのActionにShotという新規アクションを追加します。対応する入力キーはなんでもいいですが、僕は左コントロールにしています。とてもやりにくいので、おとなしく左クリックにしておくとよいでしょう。

設定が終わったら、BP_Playerに移動します。新しくShot関数を作りましょう。中身はこんな感じで、ライフルのGetShotPosをBP_Playerに同じ名前で作ってそれを使って呼び出し、BP_ShotをSpawnActorFromClassから生成しています。その後の2つの変数は今はなんの役にも立ってないので放置です。あとで色々変更するときに使います。
Shotの中身

最後にBP_PlayerControllerで、インプットアクションのShotイベントを設定します。設定したボタンが押されたとき、BP_PlayerからShot関数を呼び出します。先ほどと同じですが、離したときのイベントに設定している変数は無視してください。
ShotEvent.png

これで、全部終了です。コンパイルを通してエラーが無ければプレイしてみましょう。上下に銃口がカメラに合わせて動くようになっていて、向いている方向へと弾が飛ぶようになっているはずです。
結果

おまけ


ちなみに、単純に銃口の位置だけを取って弾を発射するとこうなります。



とても雑でわかりにくいですが、これにて今日はおしまいです。アニメーション全然使ってなかったのでとても、手間取りました・・・。
プロフィール

shiratori00

Author:shiratori00
ゲームプログラミング頑張って勉強中です。

最新記事
最新コメント
月別アーカイブ
カテゴリ
Twitter on FC2
カウンター
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QR
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。