UE4 ガンシューティングゲームを作ろう!その4 視線選択
はい!今回は視線だけでイベントが起こせるようにしたいと思います。視線選択機能を作る過程で今日もUE4の素晴らしい機能を覚えていきましょう!
スマホなどのゲームはタッチやスライドくらいでしか入力が取れません。なので、視線だけでボタンのオンオフが制御できたら、それだけ入力の方法が増えるということですね。
特にVRコンテンツを作るときは画面がタッチできないことがあるので、その時に視線選択を使うと大変便利です。(なぜタッチできないのか→ハコスコ様 こちらを見ていただけるとわかると思いますが、スマホがカードボードに覆われます。)
スマホでなくても色々な用途に使えそうですね。それでは早速作っていきましょう!!今回は、ぶっさん様の記事を参考にさせていただきます。
まず、First Person Character(プレイヤー)のBPを開きます。
開きましたらEventGraphを開きます。
すると前作ったSpline移動のBPがあります。ここあたりにノードを追加していくので、混ざらないようにこれをまとめてしまいましょう。
1.まとめたいノードたちをドラッグして囲います。
2.どのノードでもいいので、選択したノードの一つにカーソルを合わせた状態で右クリックします。するとノードアクションが出てくるので、選択対象からコメントを作成するを選択します。
3.コメントが出てくるので、好きな(わかりやすい)コメントを打ちます。今回Spline移動にしました。
これでかなり分かりやすくなりました。
それではまず、プレイヤーの視線に当たり判定をつけます。
今回もSplineの時と同様にイベントTickを使います。しかし、これは1つしか使えないので、シーケンスというものを使っていきます。
Spline移動の初めにあるイベントTickから線を引っ張り、シーケンスを出します。
これは右のThen0を最初に実行し、そのあとThen1,Then2...と続けて実行することができます。Thenを増やす時はピンを追加をクリックします。
これを使わなくてもできないこともないですが、プログラムが見やすくなるので、こういう時はシーケンスがおすすめです。
ではThen1から線を引っ張り、下あたりで離しましょう。そこでLine Trace by Channelを出します。
このノードはStartで指定した場所からEndで指定した場所まで、当たり判定(コリジョンを発生させ、当たった情報をOut Hitから出力してくれるノードです。(個人的に、スパイ対策の当たったら警報が鳴るレーザーにも使いたいノードですw)
なので今回はプレイヤーの目の位置(Cameraの位置)をStartに、Playerの視線の先(Cameraの向き)をEndに指定しましょう。
まずGet Player Camera Managerでプレイヤーのカメラを取得します。
それをGet Actor Locationをつなげることでカメラの位置をGetし、それをスタートにします。
それと、Get Actor Forward Vectorにつなぐことで、カメラの向きをGetし、それに5000かけます(Vector*Float)。それをカメラの位置に足すことで、カメラの位置から向いている方向に5000進んだ位置を求めることができます。これをEndにつなぎます(ぶっさん様の記事に詳しく書かれています)。5000の値を変えることで距離も変えることができます。
Trace ChannelをCameraに、Draw Debug TypeをFor Durationにしましょう。ここで、コンパイルをしてプレイしてみてください。
赤い線がたくさん出てきて、何かに当たると緑になるかと思います。(Draw Debug TypeをNoneにすれば線が透明になります)
しかし、まだものを見ても何も起こりません。簡単に作れるイベントは、敵を見ただけで撃つことができるイベントです。
Out HitからBreak Hit Resultを出します。そこのHit ActorからMyEnemy1にキャストします。
キャストノードの右の一番上から線を出し、もとから作られているSpawn projectileのMontage Playにつなげます。
これで完成です。プレイするときはかなり重くなるので注意してください。敵を見ただけで弾がたくさん発射されますね。
これではバランス崩壊です。ここでバランス調整として、弾が出る感覚を大きくしましょう。Float型の変数ShotWaitTimeを作り、以下のノードを追加します。
大事なところは2枚目の写真のGet World DeltaSecandsのところです。これに関してはalwei様の記事を読んでみてください。このノードは前回イベントTickが呼び出された時間から今回呼び出されるまでの時間をFloat型で返してくれるものです。ちょー簡潔にいうと、どのプレイ環境(パソコンやスマホ)でも同じ速度で弾を発射するためにつけました。
こういった感じでバランス調整をしてみましょう。
次はしばらく見続けるとスイッチが押せるというものを作ってみましょう!こまめにセーブをして、適度な休憩を取ってくださいね。
まずはゲージ部分を作っていきます。コンテンツブラウザの新規作成をクリックし、ユーザーインターフェースからWidgetブループリントを選択します。
するとWidgetブループリントが作成されるので、名前をMyWidgetとしておきましょう。
MyWidgetを開きます。Widgetはおもに2Dの部分を作るときに便利です。今回のようなゲージを作ったり、ほかにもボタンを作ったりすることができます。
画面右上にデザイナーとグラフというボタンがあります。デザイナーは下の画像のように、見た目や配置などを操作することができます。グラフでは今まで触ってきたBPのように、実動作を制g穂することができます。
今回はデザイナーだけを触ります。
画面左のパレットからProgress Barを見つけて、真ん中の画面の点線の中にドラッグ&ドロップします。
プログレスバーの周りに白い点がついているので、左ドラッグして点線の枠と同じかそれより少し大きいくらいに調整しましょう。
これでゲージのもとは完成しました。
では次はプレイヤーにみられるとこのゲージを出現させ、青いゲージがためて、そのゲージがマックスまで行くとイベントを発生させるアクターを作っていきます。MyWidgetはコンパイルとセーブをした後、閉じてもらって構いません。
いつものようにブループリントから新規のブループリントを作成します。今回はActorにします。名前はMyWidgetActorにします。(下の画像は前々回の使いまわしですw)
まずみられるための本体を作ります。BPが開けましたら、コンポーネントを追加を押し、球やキューブを追加してください。(一番下にコーンやシリンダーがあるので、好きなものを選びましょう。僕は球にしてみました)
次はゲージ(Widget)を追加します。同じくコンポーネントを追加からWidgetを選択します。
このままでは何も表示されません。先ほど作ったMyWidgetを出しましょう。
画面右側の詳細タブからWidget Classを見つけます。デフォルトではNoneになっているので、MyWidgetに変更します。
すると先ほど作ったMyWidget が表示されます。好きなように大きさや位置を変えてみましょう。見やすくするのがポイントです。
僕は球の上に表示されるようにしました。お好みでどうぞ!
次はプログラム部分を触っていきます。
まずBoolean型の変数Flagと、Float型の変数Percentを作ります。Booleanの変数は、TrueとFalse2つの状態しか持てません。これはOn,Offのフラグに使うためのものだからです。主にブランチ(if文)とともに使われます。
今回Flagは、プレイヤーにみられているかを記憶し、Percentはゲージがどこまで進んでいるかを記憶します(物体をしばらく見続けるとPercentの値が大きくなり、決めた値まで行くとイベントを起こすようにするためのものです)。
プレイヤーにみられているか見られていないかで処理を変えるので、ブランチを作り、以下のようにつなぎます。
見られていればTrueに、そうでなければFalseに行くとします。
ここで見られていればPercentの値を大きくする処理を書いていきます。色々なやり方がありますが、便利なものがタイムラインです。百聞は一見に如かずということで早速使ってみましょう。
Trueから線を出し、Timelineと打ってタイムラインを追加するをクリックします。(タイムラインについてもっとよく知りたい方は、こちらのなつのや様の記事をお勧めします)
こちらがタイムラインです。たくさんつなぐ部分があるので戸惑うかもしれませんが、とても便利なので軽く使ってみましょう。タイムラインのノードをダブルクリックします。
するとタイムラインの編集画面が出てきます。もとの画面に戻るときは真ん中の画面の上のタブにあるEventGraphをクリックです。逆にタイムラインを開きたいときはタブのタイムラインをクリックです。
これがタイムラインです。左上にある「f+」みたいなボタンをクリックしましょう。これはフロートトラックを新しく作るもので、これでFloat(フロート)型の変数Percentの値を変えていきます。名前は何でもいいですが、そこまで重要ではないので、僕はデフォルトのままにしました。
すると中央部に、何やら数字が書いたトラックが出てきます。これはx軸が時間(s)で、y軸が値になります。右ドラッグで画面を動かしたり、スクロールで画面のズームを変えることができます。ほかの画面と同じ操作ですね。
トラック内でShiftキーを押しながら左クリックでポイントを打つことができます。下の画像のように打ってみましょう。
上の画像では時間が-0.002の時値が0.011になるように点を打ちました。このように点の位置によって時間ごとの値を決めることができます。
次は5秒で値が0.265付近になるように点を打ちましょう。すると原点からゆっくり値が上がるように線が引かれます。これで時間当たりの値の変化のグラフが完成しました。
最初に作った点をクリックすると、点の場所調整ができます。下の画像の赤丸の場所の数値を変えることでも調整ができます。今回はしっかりとした値に調整します。
1つ目の点を、時間0,値0にし、2個目の点を時間5、値0.265にしましょう。あとから変えられるので、完成してからプレイをして調整してみてください。
タイムラインの設定は以上です。Event Graphに戻ってFalseをReverseにつなぎます。
タイムラインのPlayはタイムラインを動作させ、時間の値を増やしていきます。Reverseはタイムラインを動作させ、時間の値を減らしていきます。Play from Startは時間がすでに増えていても一度リセットしてから時間を増やしていくもので、Stopは時間の加減算を止めます。ほかにもいろいろな機能があるので、ぜひマスターしてください。
時間当たりの値は下の画像でいうNew Track 1から出てきます。この値をそのまま使ってもよいのですが、便利なのでPercentに保存しておきましょう。
次はこのPercentの値をプログレスバーに送り、わかりやすく色がつくようにします。この記事の最初の画像のバーの青い部分を作ります。
他のブループリントにつなげるためにはキャストを使います。今までに何度も使ってきましたね。SetノードからMyWidgetへキャストするを選びます。
画面左下にあるWidgetをドラッグ&ドロップします。そこから線を引っ張り、Get User Widget Objectを選択します。
そして下の画像のようにObjectにつなぎます。
そしてAs MyWidgetから線を出し、Get Progress Bar ~を出します。このように先ほど設置したプログレスバーをGetします。
このGetしたプログレスバーのPercentを指定するだけで青い部分を作ってくれるノードがあります。今回はそれを使います。GetノードからSet Percentを出します。
先ほどPercentに値を格納したので、Percentの値を取得し、プログレスバーに送ります。
ではここでFirst PersonCharacterのBPを開きます。MyWidgetActorをみたらFlagをTrueにする処理を書いていきます。
Line Trace by ChannelとSetノードの間にシーケンスを追加します。先ほどいじった部分ですが、ごちゃごちゃしているので探しにくいですが頑張りましょう。コメントをつけると探しやすいと思います。コメントの作り方はこの記事の最初のほうで書いています。
Then0を先ほど作ったノードにつなぎ、Then1を視線選択に使いましょう。そうすると、Then0を切断するだけで敵を見ても勝手に弾を発射しなくなります。このひと手間で管理がしやすくなりますね。
Then1から線を出し、MyWidgetActorへキャストするを出します。
As My Widget ActorからSet Flagを出します。これは先ほど作ったBoolean型の変数です。Setノードのチェックを忘れずにつけましょう。このチェックはTrueという意味です。チェックがついていないとFalseになります。
最後にHit ActorをObjectにつなげます。
まだ完成ではありませんが、ここで設置して確かめてみようと思います。SplineのSpeedを0にしてSplineのスタート位置に設置すると確かめやすいです。Widgetは前からしか見えないので、回転させて見えるようにします。物体を回転させるにはビューポート上部のいかにも回転というボタンをクリックして、回転させたい方向に対応している扇形をドラッグします。
そしてプレイすると、ゲージが増えていくようになりました。しかし視線をそらしてもゲージが減りませんし、何も起こりませんね。
またMyWidgetActorを触っていきます。タイムラインとTrueの間でFlagをFalseにします。見続けることでこのFalseをTrueにできますが、見なくなると途端にFalseになり続けるといった感じです。
これだけで別のものを見るとゲージが減るようになりました。次はマックスまで行くとイベントが発生するようにします。
Finishedから線を出し、以下のようなノードを打ちます。
Percentが0.265より大きくなったらTrueにつながるので、Trueの先に繋げたことがマックスまで行ったイベントになります。タイムラインの値を変えた人は(~より大きくなった)の~の部分を変えるといいと思います。
今回はOpen Levelを使います。これは名前の通りLevelを開くノードです。
OpenLevelノードに直接Level名を打ってもいいのですが、その名前を変数化すると便利です。名前型の変数Level Nameを作ります。編集可能にしっかりとチェックをつけてください。
Default名をとりあえずMyLevelにしてノードをつなぎます。
これでゲージがマックスまで行くとMyLevelに飛ぶようになりました。同じレベルに飛んでいるので感動が薄いですが、別のレベルに飛ぶことも可能です。
BPではゲームプレイ中に物体を見えなくしたり、見えるようにしたりすることができるノードがあります。それを使ってゲージの値がが0より大きいときゲージが見えるようにして、0以下の時見えなくしたいと思います。
案外どこでもいいのですが、ここにプログラムを打っていきます。このブランチでTrueのとき見えるようにして、そうでないとき見えないようにします。
Trueから線を引っ張り、Set Hidden in Game(Widget)を出します。Falseの先にも同じように出します。
このノードのNew Hiddenのチェックをつけると消え、チェックをつけないと見えるようになります。以下のようにしましょう。
これで青い部分があるときには見えるようになり、数値が0になると見えなくなります。
しかしウィジェットは見えないだけで存在はしているので、この際当たり判定を消してしまいましょう。
画面左のWidgetをクリックし、右側に詳細を出します。詳細のCollisionのコリジョンのプリセットをNoCollisionにします。これで当たり判定がなくなりました。
これでほとんど完成ですが、実はこれでは不具合が生じてしまいます。視線選択に使ったLine Trace by Channelですが、これは最後に線に当たったものをOutHitから出します。なので、敵を観た後に地面などの他の物体に線を当てずに素早く空を見ると、ずっと弾を撃ち続けてしまいます。視線選択も同じで、ゲージが増え続けてしまいます。
色々な解決法がありますが、今回はLine Trace by Channelで作った当たり判定の線の終点に、其れだけに反応する(敵や弾は貫通する)ダミーのアクターを置いて解決しようと思います。
ブループリントからActorのBPを作ります。名前はMyDummyActorにしました。
BPを開いてコンポーネントを追加から球を選びます。
このアクタは常に視線の先の末端にいてほしいので、そのようにプログラムを打っていきます。どうせなのでコピーを使ってみましょう。
First Person Characterを開き、下の画像の赤丸の部分を範囲選択し、右クリックからコピーを選びます。(WindowsではCTRL+Cでもできます)
またMyDummyActorに戻り、適当なところで右クリックし、ここに貼り付けをクリックすると、貼り付けができます(CTRL+Vでもできます)。
イベントTickからSet Actor Locationを出します。これはActorの位置をダイレクトに決めるものです。今回は視線の5000進んだところに位置をSetしています。
これでプログラムは完成です。次はこれを見えなくして当たり判定を変えていきます。
見えなくするには画面左にあるMyDummyActorをクリックし、詳細のRenderingにあるActor Hidden in Gameのチェックを入れることで消せます。
先ほどのようにゲーム内で見えたり見えなくしたいのならばプログラムで、ずっと見えなくするならこちらのように設定するといいでしょう。
次は当たり判定を変えていきます。画面左のSphereをクリックし、詳細を出します。詳細のCollisionからコリジョンのプリセットを変えます。その前に今回はいつもよりも細かくいじるので、コリジョンのプリセットの左にある▷ボタンを押してより細かい詳細を出します。
コリジョンのプリセットをCustomにしますこれにより、自分独自の当たり判定を作ることができます。今回はほとんどの物体には反応してほしくないので、コリジョン応答を無視するにして、一度すべての当たり判定をなくします。
このままでは何にも反応しないので、Line Trace by Channelで出した当たり判定に反応するようにします。
First Person CharacterのLine Trace by Channelノードです。
ここでTrace ChannelをCameraに設定したので、Cameraの部分だけブロックにチェックを入れます。
最後にCollision EnabledをNo Physics Collisionにします。
これで完成です。マップに適当に1つ設置すると、自動で視線の先の末端に移動して仕事をしてくれます。
どうせなのでステージ選択画面を作ってみます。
MyLevelに戻ってファイルから新規レベルを作成します。今回もDefaultを選びます。名前はSelectLevelにしました。
ここで復習です。プレイスタートを消去し、FirstPersonCharacterを設置し、それをプレイヤーにしてみましょう。
設置した後、PawnのAuto Process PlayerをPlayer0にするんでしたね。これについてはこの記事のその2にわかりやすく書いていますので、わからない方はどうぞ。
ここでプレイするとなぜかプレイヤーが地面に埋まってしまいます。それはなぜかというと、SplineがないのにSpline移動をしようとしているからです。どうせなので治しましょう。
変数からSplineを取得し、MySplineActorにキャストします。このSplineの値があればキャストに成功し、正しく動作します。Splineの値がなければCast Failedに行き、そこで処理が終わります。なのでマップにSplineがあっても下の画像のようにSplineの値をなしにしているとSplineに関係なく自由に動くことができます。
このちょっとしたノードで普段は普通に操作できて、一定の場所に行くとSpline移動になるなんてことも可能になります。
では視線選択を設置していきます。
このようにどのレベルに飛ぶのかを変数化したおかげで、複数個おいてそれぞれ別のレベルに飛ぶようにしてみました。左がMyLevelで右がSelectLevelです。
DefaultをSelectLevelにしてもいいかもしれませんね。こちらはその1でやり方が書いてあります。もう一つLevelを作って別のコースを作ってコースを選べるようにしてもいいかもしれませんね!
はい!今回はこれで以上です!!回を重ねるごとに長くなっている気がしますが気にしないでおきましょう。こまめなセーブ、こまめな休憩が大事です(まあやりたいときにやるのが一番だと思いますが…)。
まとめ
・プログラムをコメントでまとめました
・シーケンスを使いました
・視線に当たり判定をつけました。
・敵を見ただけで撃つようにしました
・どの環境でも同じ速さで動作するようにしました(自動で弾が出てくる速さ)
・Widgetを作成しました
・視線選択を作りました
・レベルを飛べるようにしました
・タイムラインを使いました
・物体の表示非表示を切り替えました
・当たり判定をより深く制御しました
・Splineを改良しました
※FirstPersonCharacterの追加分
※MyWidgetActor
※MyDummyActor
今回もたっぷりボリュームになったかと思います!次回はある場所に行っただけでイベントを発生させることができるトリガーボックスについて書いていこうと思います。Splineの速さを途中で変えてみたり、最後まで行ったらSelectLevelに飛ばしたりいろいろできそうですね。今回で結構BPに慣れてきたのではないかと思いますがどうでしょうか。慣れてきたらどんどん物怖じせずにいじってみてください!
では、今回はこの辺で!