UEを学ぶ「オブジェクトの生成を学ぶ_4_spawnで弾を発射する_2」
◆弾が当たった時に音が鳴る
弾が体に当たったならズキュンバキュンと音を鳴らしたい。
ついでに、当たったら消えるようになっていてほしい。
やることはシンプルで、
Overlapした(重なった)時に弾から音が鳴って、
その後デストロイしてくれればいいわけだ。
というわけで以下のようなコードを追加する。
Cast To ThirdPersonCharacterは、
プレイヤーに当たったときにのみ反応するという条件だ。
上記の設定でもうまくいくが、動画中ではとある問題が発生している。
弾が生成と同時に消滅しているのだ。
なぜか?
Castによって対象を指定していない場合、
自分自身とオーバーラップしてしまうため、弾が出現と同時に消えてしまうのだ。
(自分のあたり判定Boxと、オブジェクトSphereがぶつかっている)
なので、
NoCollision(衝突判定なし)にすることで、
自分自身に衝突することを回避している。
他にも、衝突の属性自体を細かく指定することでも
解決することができる。
◆弾を雨のように撃つ
ある一定の範囲にランダムに弾を生成しまくるBPを作成する。
まず初めに、Spawnを行うBPの板を作る。
BP>ブループリントクラス>Actor で
アクタを作成。名前は「BP_BulletRain」にでもしておく。
オブジェクトの中では
コンポーネントを追加 > box collision を選択。
雨が発生する天井として薄く引き伸ばす。
更に、方向を設定するArrowコンポーネントを追加。
向きは真下を指すようにしておく。
次にBPのイベントグラフを作っていく
まず、 スポーンアクタ を生成して
イベントTick と接続する。
スポーンアクタの生成物には「Bullet」を設定。
SpawnTransform(スポーンする座標)には、
Arowの位置を使用する。
これだと、弾はArrowの座標からまっすぐ落ちるだけとなる。
次に、Boxの範囲でランダムに発生するようになってほしい。
そこで使うのが
「Random Point In Bounding Box」という機能だ。
Boxコンポーネントの範囲からランダムに座標を取得する機能となる。
RandommPointInBoundingBoxにBoxコンポーネントの中心位置(GetWorldLocation)を
原点(Origin)として設定。
さらに、範囲(Extent)をBoxコンポーネントからGetBoxExtentで取得、
設定する。
これにより、Boxの範囲でランダムに弾を生成しまくるBPが完成したわけだ。
というわけで、こんな感じ。
なぜ弾がブドウのように大きいのか。それは謎だ。
◆ホーミング弾を作る
実は、ThirdPersonの位置を確認して弾をホーミングさせることもできる。
BP_Cannonに変数を追加(「NewVar0」が現れる)し、
オブジェクトタイプを「ThirdPersonCharacter」に設定し
Characterとして変数名を設定。
変数名横の目玉アイコンをクリックして、
開いた状態にしておく。
レベル上のアウトライナから
BP_Canonを選択し、
詳細 > デフォルト
が追加されているので、
そこのCharacterパラメータにThirdPersonCharacterを設定する。
同じように、BP_BulletにCharacter変数を追加。
ただしこちらは、目玉のアイコンが開いた状態で
変数>スポーン時に公開 を有効にする必要がある。
これを行うことで、
弾を生成するときにBP_Canon→BP_Bulletでパラメータを渡すことができる。
BP_Canonを開き、スポーンの値にcharacterを付与する。
そして、今度はBP_Bullet側にプレイヤーを追跡する仕組みを入れる。
CharacterからGetRootComponentを行い、
それをHomingTargetComponentに設定。
するとキャラクターの胸あたりが狙われるように設定される。
(ちなみに、キャラクターのmeshを指定すると、足元を狙われてしまう。
これはスケルタルメッシュの原点が足元であるため)
ちなみにホーミングの設定や、弾の寿命を設定することができる
・弾が何秒か後に消えるのを設定するのは
BP_Bullet(Self)>詳細>アクタ>Initial Life Span
を設定する。
・ホーミングの設定は
ProjectileMovement>詳細>ホーミング
から行える
ちなみに、「イベントEndPlay」を利用することで
弾が当たったり、時間切れで死んだときに演出を追加することも可能だ。
また、動画中では軌跡だけを残してきれいに消す方法に言及していた。
が、ちょっと複雑そうなので次回…
UEを学ぶ「オブジェクトの生成を学ぶ_4_spawnで弾を発射する」
大砲的なものから弾を出す仕組みを作る
Spawnerを使って、弾を出す大砲を作ろう、
というもの。
◆大砲の弾を作る
早速BPで弾のアクタを作る。
右クリック>ブループリントクラス>Actor
でアクタを生成する。名前はBP_Bulletあたりに。
生成したアクタをダブルクリックして
コンポーネント画面を開き弾の形状を整える。
弾の形状の変形は画面右上の「オブジェクトを選択して拡大・縮小」を選択し、
オブジェクトの矢印を引っ張ったり縮めたりして行う。
これが、ちょうどいいサイズ感がなかなか難しく、
レベル上に配置して何度も確認した。
オブジェクトの構成も一工夫必要。
まず、アクタを一直線に飛ばすための機能である
Projectile Movementを追加する。
Projectile Movement>詳細 からSpeedを設定することで、
その速度で弾が移動する。
また、Projectile Gravity Scaleが設定されていると、
重力に引っ張られて弾が落ちてしまうため
0に設定する。
ただし、これだけだと弾の尖っている方が先頭にするというのが難しい。
まずは
Projectile Movement のRotation Follow Velocityを有効にしておく。
これを有効にしておくと、進んでいる方向に向かってアクタの位置を調整するため
常にまっすぐ弾が進む。(らしい)
また、このままでは弾の向かう方向が設定されていないため、
Arrowコンポーネントを追加する。
Arrowコンポーネントの矢印の先端に合わせて、アクタが向きを合わせてくれる。
ここまで設定することで、「まっすぐ進む弾」が完成した。
最後に、SphereがBox Collision下に入るようにして、
当たり判定を設定する。
黄色い箱が当たり判定になる。
いい具合になるようにサイズを調整していく。
追加したBox > 詳細 >コリジョン
で、コリジョンアセットを設定。
動画中では、まずはまずはBlock All Dynamicに設定していた。
これを設定すると、何にでも衝突するので、跳ね返ってくる
なぜ跳ね返ってくるのか?
それはProjectile Movement のShould BounceがONになっているからである。
大砲の弾としては、
上記項目は不要なのでOFFにしておこう。
すると、弾は反射せずに刺さる(壁で停止する)ようになる。
これで弾の完成だ。
◆大砲を作成する
同じように
右クリック>ブループリントクラス>Actor
アクタを作る。名前はBP_Canonに。
作ったアクタをダブルクリックで開いて、作成を開始する。
アクタの見た目は適当にありものを使う。
コンポーネントを追加 > Static Mesh
で、コンポーネントを追加し、
「詳細」からサンプルから大砲っぽいモデルを配置する。
次に「一定間隔で弾を撃つ」という挙動を付与する。
イベントグラフタブへ移動
今回は「イベントTick」を利用した実装を行う。
Tickとは、毎フレーム実行するイベントである。
「常に〇〇をする」というものだと思っておけばよい。
次に、「クラスからアクタをスポーンする」を追加する。
そして、クラス名に「BP_Bullet」を設定すると、
ノード名が「SpawnActor BP Bullet」となる。
が、これだけだとエラーが出る。
Spown Transformに生成する位置を設定する必要があるのだ。
ノード内のSpawnTransformを右クリック > 構造体ピンを分割
で内部要素をLocation,Rotation,Scaleの3つに分割する。
この時、座標の設定はそのままBP_Canonの位置を使うことができない。
ノード中のCollision Handling Overrideが有効になっており、
自身の座標を発射位置にすると、弾の登場位置に大砲があって
スポーンできないというわけだ。
大砲から発射する弾の向きと位置を設定するため、
コンポーネントの追加 > Arrow
を追加する。
作成したArrowをイベントグラフ上にドラッグ&ドロップ
GetWorldLocationノードを追加し、
Arrowの座標を取得して、Spown Transform Locationに接続する。
これでともかく弾が出るはず…!なのですが、
これで実行すると弾同士が干渉して弾が出現しないです
BP_Bulletのあたり判定を「OverlapAllDynamic」として
弾がぶつからないようにしよう。
更に一座標同様に、
GetWorldRotationでArrowの向きを取得。
これでようやく、意図通りの方向に弾を撃てるようなった。
弾の感覚が短いと感じた場合
「イベントTick」の詳細 > アクタティック > Tick Interval(secs)を
1にしておこう。
これは処理を何秒ごとに行うか?の設定であり、
弾を発射する間隔を広くしたのだ。
残像みたいになっているのが大砲の弾である。
最後に、大砲発射時にSEをつけていく必要がある。
※ちなみに、UE4は「wav」ファイル形式しか対応していないため
mp3が使えないとのこと。
Spawn Sound at Locationを追加し、
Spawnactorの末尾に接続。
Volume Multipulirのパラメータでいい感じにサウンドを調整したら完了だ!
(ちなみに、弾側のイベントBeginに音を設定しても、同様の結果になる。
これは、大砲が弾を生成した時にBeginで音を鳴らすため、
タイミングが実質同じになるためだ)
UEを学ぶ「オブジェクトの生成を学ぶ_3_spawnでプレイヤーエフェクトをつける」
Q&Aにあったプレイヤーにダメージエフェクトを付ける話。
冒頭、頭にオブジェクトつけたりしているが、
本筋には関係ないのでカット。
◆作り方
まず、ダメージを受けたことを検出するために
右クリックから
add custom event
でカスタムイベントのノードを作成。
「ダメージを受けた」と名前を付ける。
続けて
「Spawn Emitter Attached」ノードを追加。
※「Spawn Emitter Attached」はオブジェクトを対象にエフェクトを発生させるノード
コインの「Spawn Emitter at Location」は座標基準の設定だった
(結局コインの位置自体を座標に指定していたが…)
Attached to ComponentにはコンポーネントのMeshをドラッグ&ドロップし
接続する。
Emitter Templateには初期から入っている「P_Fire」を設定。
そして「Attach Point Name」には「head」と入力。
これで頭パーツに炎が追従されるはずなのだが…、
なぜか胴体に発生してしまったのでZ=100に設定しておく。
(モデルを変えているせいだろうか…)
Location Typeは「Keep Relative Offset」に設定する。
※Keep Relative Offsetはオブジェクトとの相対距離を維持する設定
最後にエフェクトを確認するために
「イベントBegin Play」ノードと、先ほど作った「ダメージを受けた」ノードを用意し
ゲーム開始からダメージを受けた状態をONにしておく。
上記の設定で再生すると、
以下のようにキャラクターに炎が出ている状態になる。
ちなみに、このダメージの発生の正式な判定自体は、
講義中では扱われないので
別途考える必要がある…。
UEを学ぶ「オブジェクトの生成を学ぶ_2_spawnを使ってコインに音とエフェクトをつける」
引き続き、コインを作っていきます。
コインを獲得した時の音とエフェクトを付与します。
が、その前に「音」と「エフェクト」を用意する必要があります。
ラーニングから「機能別サンプル」というプロジェクトをインストールし
ライブラリから開きます。
この「機能別サンプル」、UEで予め用意されている様々な素材を
閲覧することが可能なプロジェクトです。
コンテンツ > Maps
から様々なレベルを開き、各素材を閲覧することができます。
目当てのアセットを見つけたら
右クリック > アセットアクション > 移行
で自分のプロジェクトに移行させましょう。
また、フィルタ機能を使うと効率よく目当ての素材を探すことができます。
フィルタをクリックすると、アセットの項目が羅列されるので
エフェクトを探すために
パーティカルにチェックを入れる。
フィルタは複数設定可能で
やめたい場合は、「フィルタ」の下にある
「パーティクル」といった文字列をクリックする。
素材集めが終わったら、元のプロジェクトに戻ろう。
================================
◆BPを使って音と演出の再生を行う
まず音を鳴らすために、
コインのOn Component Begin Overlap()にSpawn Sound2dを紐づける。
Spawn Sound2dのSoundに、先ほど集めた音素材(TextPop)を紐づける。
これで、音が鳴るようになった。
(ちなみに、ReturValueから「FadeIn」や「SetPitchMultipler」を使うことで、
フェード演出や音量調整を行えるようだ」
※この「Spawn」というのが、何かを生成するというものなようで
音を生成している、という考え方なようだ
加えて、エフェクトを再生するために
Spawn Emitter at LocationをSpawn Sound2dに接続する。
実は、Spawn Emitter at Locationだけだと、
正しくエフェクトが表示されない。
なぜかというと、再生する座標が(0,0,0)になっているからだ。
実際には、コインの座標でエフェクトを生成してほしいため、
GetActorLocationをSpawn Emitter at LocationのLocationに接続する必要がある。
これでコインの完成だ。
UEを学ぶ「オブジェクトの生成を学ぶ_1_コインの雛形を作る」
イベントトリガーを学んだところで、
実際にコインを作ってみる。
■コインのモデルを作る
いつもの流れでActorを追加し、BP_Coinとします。
BP画面を開いて、
+コンポーネント > Static Mesh
を追加。
StaticMeshの詳細から
スタティックメッシュ > Shape_Tours
を追加して、円形のコインリングの完成。
レベル(フィールド)上に配置して、
回転角を設定し、
トランスフォーム > 拡大・縮小
からX:0.5、Y:0.5 に設定。
いい感じのサイズになる。
マテリアル > エレメント0
に M_Material_Gold を設定する。
動画の完成図的にはこんな感じでした。
ただ、このままだとそもそも接触しても消えないので
BPを設定する必要がある。
On Component Begin Overlap(Sphere)
は重なったタイミングで起動するトリガーとなる。
DestroyActor(Actorを消す)を接続することで
「ふれたら消す」というActorが作られる。
更に、現状の当たり判定だと、他のActorが接触しただけで消えてしまう。
ゲーム的にはプレイヤー(Pawn)にぶつかった時だけ消えてほしいため、
BP_Coinの
をCustomに設定しオブジェクト応答の設定を行っていく。
各項目について「無視する/オーバーラップ」を選べるため、
今回はPawn(プレイヤー)のみオーバーラップするようにする。
これで、プレイヤー(Pawn)のみが接触した時に
消滅するコインの雛形が完成。
次は、コインの中身を作っていく
UEを学ぶ「トリガーを作る_イベントトリガーについて学ぶ」
チュートリアルを見ていたら、
急にスコアの取得をやり始めたので、
しぶしぶ過去の話数を見返す。
---
■トリガーを使った設定
始めに、コリジョン用のアクタを使った方法が説明された。
アクタから「ボックストリガー」をドラッグ&ドロップで
フィールド上に配置することで
ボックスに触れると起動されるスイッチを配置されたことになる。
(※詳細>レンダリング>Actor Hidden In Game をチェックすることで
プレイ中も確認することができる)
また、表示設定を「可視性コリジョン」にすることで、
コリジョンだけが見える状態にすることもできる。
■コリジョンを使った設定
アクタにコリジョンを設定し、
コリジョンの当たり判定を広げることで
接触判定を行おうというもの。
右クリック>プループリントクラス>Actor
でブループリントクラスを作成。
(名前は適当に BP_SpotLight に)
「コンポーネントを追加」>Cube
でキューブを配置し、さらに
「コンポーネントを追加」>Box Collision
で当たり判定を追加する。
追加したBoxコリジョンを引き延ばして、
ブロックの足元を通ると当たり判定が検出できるようにする。
(※ちなみに白い球体は中心となる目安なので、画面上に表示されるわけではない)
作ったアクタはレベル上に配置する。
ビューポート から イベントグラフ へとタブを切り替えて
BPを編集する。
変数>+
をクリックするとboolean型の変数(赤いやつ)が追加されるので
「今グレイマン入ってるよー」はTRUE/FALSEの二つの値をチェックボックスとして
持っている。
「今グレイマン入ってるよー」をドラッグ&ドロップすると
以下のように2択を迫られる。
Setは代入でGetが参照。
今回は
・「グレイマンがコリジョンに入る(Begin Overlap)と『今グレイマン入ってるよー』にONを代入」
・「グレイマンがコリジョンから出る(End Overlap)と『今グレイマン入ってるよー』にOFFを代入」
という形にしたいので、
Set(代入)を配置して、白矢印で接続する。
※「グレイマンがコリジョンに入る(Begin Overlap)」では「True」(チェックボックスをON)にしておく
---
とはいえ、この辺はいろいろなやり方を紹介するパートで
何かに着地はしないのだが…。
紹介されていた別の方法では、
Graymanのアクタをセットで配置し、
OtherActor(Grayman)がBegin Overlapしたかどうかを、
Graymanに代入。
その結果をIs Overlapping Actor関数の引数として使用することで
「Graymanが作成したコリジョンに接触していることを検知すると何かしらの処理を行う」
という構成を作ることができる。
イベントTickはゲームを起動中にマイフレーム呼ばれる処理なので、
ブランチを組み合わせて
「マイフレーム確認して、GraymanがBoxに触れたらTrueとなり、何らかの処理を行う」
※ブランチより先がないので「何をするか」は未定
という構成となる
ちなみに、何にぶつかって、何にぶつからないかは
コリジョンレスポンスを利用して設定する。
以下の3つからチェックボックスを設定し、相互にぶつかった際にどのようにするかを決める。
Ignore |
|
Overlap |
もう 1 つの物理ボディが [Overlap] または [Block this Physics Body's Object Type] に設定されていると、Overlap Event を発生させることができます。 |
Block |
もう 1 つの物理ボディが [Block this Physics Body's Object Type] に設定されていると、Hit Event を発生させることができます。 |
▼詳細はこちら
いったん長くなったので次へ
UEを学ぶ「タイトル画面を作る_3_遷移時のフェードアウト」
Q&Aで触れられた画面遷移時のフェードアウト処理について作っていきます。
タイトル画面に文字を表示したときと同様に
コンテンツブラウザ上で
右クリック>ユーザーインターフェース(一番下)>ウィジェットブループリント
でUIを追加します。
名称は「UMG_FadeIn」。
(ウィジェットは「UMG_〇〇」ってつけて管理していくみたいですね。
これはウィジェットが元々Unreal Motion Graphics UI デザイナ (UMG) という
機能名であることに由来しているようです)
ウィジェットを開き、パレットから「Border」を検索し
ドラッグ&ドロップで画面に追加。
詳細>アンカー
のパラメーターを
位置X 0、位置Y 0、サイズX 1920、サイズY 1080
として、画面サイズぴったり覆うような真っ白い画像が作成されます。
その後、
階層>[UMG_FadeIn]>[CanvasPanel]>[Border]
が選択された状態で
アニメーション>「+アニメーション」というボタンを押します。
すると「NewAnimation」というアニメーション設定が追加されるので
FadeOutと名付けて、フェードアウトアニメーションを作りましょう。
(今更なんですが、FadeInを作っているのにアニメーションはFadeOutって変ですね。
本来はウィジェット名もFadeOutにするのが正しいんでしょうね…)
アニメーションを選択すると「タイムライン」というタブが表示されます。
タイムライン>「+トラック」というボタンを押し「Border」を選択することで、
「Borde_0」というのがトラック上に出現します。
さらに「Borde_0」の右部にある「+トラック」を選択し「BrushColor」を追加。
「BrushColor」を展開すると、
Borderの色設定をRGBAで行える項目があるので
0秒時点をRGBAすべて0にして「透明」を設定。
右側のタイムライン上にある縦棒を動かしていき
1秒時点の色をRGBが0、Aが1に設定することで、
1秒間かけて透明から真っ黒に変化するアニメーションを作ることができました。
次に、これを「UIを画面に追加したタイミングで再生する」プログラムを設定します。
画面右上から「グラフ」をクリックしてプログラム表示に切り替えて、
「PlayAnimation」ノードを追加します。
※「FadeOut」は
マイブループリント>Animations
内にあるので、ドラッグ&ドロップし「GetFadeOut」を選択します。
追加した「FadeOut」はInAnimationに接続。
次に、Titleに組み込みます
ブループリント>レベルブループリントを開く
などで、Titleのブループリントを開き
Classにはさっき作った「UMG_FadeIn」を指定し、
ブランチから接続する。
(ちなみにノードの切断はAlt+左クリック)
これで、
「特定のキーを押すと、フェードアウトが生成される」
という一連の流れができます。
「ReturnValue」からドラッグし
「AddToViewport」ノードを生成。
(他の接続穴からだとちゃんと検索されない?ので、ReturnValueから引っ張って
Viewportで検索するのがオススメ)
更に、フェードアウト仕切るのを待って遷移してほしいため
「Delay」ノードを追加し、値を1秒に。
(Dキー+左クリック で追加可能)
これで、1秒かけて画面が暗くなり、1秒経過と同時に遷移が起こる、
という挙動になるわけですね。
ちなみに遷移後のFadeInは、遷移先の画面で作る必要があるみたいです。