3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

プログラミング無知勢のBluePrint

Posted at

初めに

この記事はUnrealEngineで初めてプログラミング・ビジュアルスクリプトに触れた人に向けたものとなります。既にUE4・UE5でBPをある程度触っている方にはほとんど参考になりません。
またC++全くわかってない勢が今後の自分のような人の為書いているので、独自解釈などが入っている可能性があります。なにか間違いがあればご連絡ください。

基礎知識として
猫でもわかるUE4を使ったゲーム開発超初級編
1 https://youtu.be/ztv4OPc_o6g まずはプロジェクトを作ってUE4エディタを触ってみよう!
2 https://youtu.be/JrQh1lVrEjM Blueprintをさわってみよう
3 https://youtu.be/Wd8Akctzhbc コリジョンを使ってコインを拾ってみよう!
までをなんとなく理解していることを前提としています。

環境:UE5.0.2

目次

ノード紹介

Tick/Print String
Sequence
MultiGate
変数
Boolean
Integer, Flote
Name,String,Text
Vector,Rotation,Transform
CastとGet Actor Of Class

Tick/Print string

スクリーンショット (570).png

Tickは1fpsにつき一回呼び出されるイベントになります。
fpsはUE5ですとしたのコンソールコマンドに stat fps と入力することで確認できます。
(プレビューの右上にこのような表示が出ます)
スクリーンショット (569).png
大体1秒間に16回処理が実行されているということになります。

スクリーンショット (572).png

Print Stringは実行される度にIn Stringの文字列を画面に表示するものになります。
デフォルトではHelloと入っていますが、文字を打ち換えたり、左側のピンクのピンに変数などを入れることによって色々なものを表示させることができます。デバッグでめちゃめちゃ使います。
開発のみ の▽を押すと詳細設定を出すことができます。
スクリーンショット (573).png

パラメータ 内容
Print to Screen スクリーンに表示するか
Print to Log アウトプットログに表示するか
Text Color テキストの色
Duration 表示する秒数

Keyは中の文字列を設定することによってPrintstringをTickで表示した時に一つの文字列を更新し続けるように設定できる?用です。

TickにPrintstringを繋いだもの
スクリーンショット (577).png
プレイ結果
noilly_magic_プレビュー__NetMode__Standalone____64-ビット_SM5__2022-07-03_13-51-40_AdobeExpress.gif

TickにPrintstringを繋ぎKeyを変更したもの
スクリーンショット (578).png

プレイ結果
noilly_magic_プレビュー__NetMode__Standalone____64-ビット_SM5__2022-07-03_21-52-38_AdobeExpress.gif
何かのパラメータなどをデバッグするときに便利かもしれません

Sequence

スクリーンショット (580).png

シーケンスは通常1つずつしか繋げられないノードを枝分かれさせられるノードです。すべてのピンが同時に実行されます。
右下の ピンを追加 で枝分かれの数を増やすことができます。

プレイするとと3つのPrintstringが実行される処理を組んでみました。
スクリーンショット (559).png
実行するとこのような結果になります。
スクリーンショット (562).png
Then0から実行されていくようです。
注意点として、実行順が先のところにDestroyActor等アクターを消したりする処理を書いて後の方にDestroyActorするアクターに関する処理(ダメージ処理・エフェクト等)を書いたりすると、対象のアクターが無い、などのエラーが出る原因になります。
必ずDestroyActorなどの破壊的処理は最後に書きましょう。

MultiGate

スクリーンショット (582).png
マルチゲートはシーケンスと同じく実行結果を枝分かれさせられるノードになります。
違う点としては、右の出力ピンが同時に実行されるのではなく、一度実行されるごとにOut0、Out1、Out2…というふうにピンが変更されていく(一回の実行につき一つのピンしか実行されない)というところです。
同じく ピンを追加 で出力ピンを増やすことができます。

パラメータ 内容
Reset 実行済みのピンを非実行状態に戻す
Is Random ピンの出力順をランダムにする
Loop 全てのピンが実行されたあと、リセットして再び実行
Start Index スタートするピンを指定できる

1秒に1回実行される処理を書きました。
スクリーンショット (567).png

プレイ結果
neutral_AdobeExpress.gif
ランダムをTrueにした場合
random_AdobeExpress.gif
(見えにくいです1 0 2の順番で実行されています)
ループをTrueにした場合
loop_AdobeExpress.gif

ループとランダムを両方Trueにした場合は102.021.120のようにすべてのピンが表示されてからループするようになります。
また、Start Indexで1以上の数値を指定すると、120と実行されます。
そこにランダムを足すと102.120のように指定した数字以外がランダムに表示されます。
ループを足すと12.012.012…という実行結果になります。
ランダムとループを両方Trueにすると120.102.102…のように指定した数字が最初に実行され、残りのピンがランダムに実行、すべて実行されるとまた指定した数字から…というふうになります。
完全に表示をランダムにしたい場合は
スクリーンショット (583).png
このように完全にどれか実行される度にResetですべて非実行にしてしまうことで121100212010…みたいな感じのランダムにすることができます。(これは例であってサイコロのようなものを作りたいのであればランダムな数値を指定した範囲で出してくれるノードがあります(後述))
これを応用すると話しかけると一方的にしゃべり続けるNPC的な物が初心者でも作れたりします。

変数

スクリーンショット (589).png

これがちょこっとわかるとかなりできることが広がります。もうゲーム制作においてありとあらゆるものが変数で管理されているといっても過言ではありません。
基本的な使い方は、
スクリーンショット (584).png
画面左下の変数というところをクリックして新しい変数を作ります。
スクリーンショット (586).png
右側の詳細パネルで名前と型を変更できます。
スクリーンショット (595).png

変数は最初は基本的に数値系は0、テキスト系はNoneか空白が入っていますが、コンパイルした後出てくる右側の詳細パネルの下の欄のデフォルト値というものを設定することによって初期の値を変更することができます。(HPという変数を作ってデフォルトを100にしたり、等)
スクリーンショット (593).png
基本的に使うのはこの二つで上のものが Get (変数名)で変数の中身を出力するもの、Set(変数名)で変数の中身を入力、変更できます。ノード自体は右クリックで検索からget/set(変数名)と検索するか、左側の変数のところからD&Dすることで出すことができます。

変数には型というものがあり、型同士で変換できたりできなかったりします。この記事では特によく使うもののみ紹介していきます。

Boolean

スクリーンショット (593).png
TureかFalseを返す変数です。ざっくりいうと今このコリジョンに入っているか?みたいな判定の時に使います。
ブランチ(Branch)ノードとセットで使うことが多いです。
スクリーンショット (591).png
ブランチノードはこのように左下にBooleanの入力ピンがついています。ここに先ほどのGet~の方のBooleanを繋げると、TrueかFalseかによって出力先が変わります。(繋げなくても左下のチェックボックスにチェックを入れるとTure、空だとFalseが出力されます。)

スクリーンショット (599).png

Booleanによく使うノードとしては上のようなものがあります。
左側は論理演算と言ってboolean動詞を比較して、真ん中に書いてある文字の条件に当てはまった時にTrueを返す、というものがあります。
2つのBooleanがorやand等の条件に当てはまればTrueを返すというものです。
右は条件式でInteger(整数),Integer64(Integerより大きな整数を使える),flote(浮動点少数)を左側に入れることができます。上下の数字を比べた時<や==等の条件に当てはまればTrueを返すというものです。
ピンを追加 が書いてあるものは追加すると左側の入力ピンが増えます。
これを使うとギャルゲのようなものを作る時、「このキャラの好感度がいくつ以上でかつこのイベントとイベントとイベントをクリアして且つこのイベントに進んでいない時に発生する~~」みたいなものが作れます。

Integer,Flote

スクリーンショット (605).png
Integer,Floteはどちらも数字を扱う変数です。
Integerは整数、Floteは浮動点少数。(雑に言うなら小数点以下を扱えるのがFloteと覚えておけばいいです)
Integer64はIntegerより大きい桁の数字を扱える整数の変数になります。(初心者のうちはほとんど使うことはないので紹介しません)
Floteは後に紹介するVectorに掛けたり、数学的な計算に使ったりと使い所がかなり多いです。

スクリーンショット (606).png
Integer,Floteによく使うノードとしては上のようなものがあります。
左は一般的な四則演算になります。ピンを追加で左側の入力ピンを増やすことができます。
剰余算以外は上下にIntegerとfloteをどちらでも入れることができます。(Flote + Integerのように違う変数同士でもできます)
右側はランダムな数字を出すノードになります。
上で書いた完全にランダムな数字を出すノードがこれになります。
Random ~~~~ In Rangeが使用回数がとても高く、Min(最小値)からMax(最大値)の間の数字を返すものになります。正確では困る物(敵AIのAimなど)やダメージに使うことが良くあります。
Random Floteは0~1の間の数値を返すものになるので二点間を移動するものの移動の割合などに使ったりします。
Random Integerは0からMax-1の数字をランダムに返すものになります。(あんまり使ったことはないです)
他にも三角関数や円周率、内積を出してくれるノードがあるのですが、数学弱者なので割愛させて頂きます。(説明できないので…)

BooleanとIntegerを組み合わせてありそうなBPを組んでみる
この二つの変数を使った例として「範囲内に入るとHPが回復する」というBPを組んでみます。

BPを作ってビューポートからBoxCollisionを出します。
スクリーンショット (601).png
特に今回範囲を示すためのものを出したりしないのでわかりやすくするために右側の詳細からHidden in Gameを切っておきます。こうすることでプレイ中もコリジョンの枠が表示されるようになります。
スクリーンショット (608).png
イベントグラフに移動してBPを書いていきます。
BoxCollisionに入ったイベントと出たイベントを追加していきます。
イベントはイベントグラフに移動し、左上のコンポーネントタブを右クリックしイベントを追加にカーソルを合わせると、追加できるイベントが表示されます。そこからOnComponentBegenOverlapとOnComponentEndOverlapを追加します。追加はコンポーネントタブからBoxCollisionを選択した時に出る右側の詳細タブからも追加することができます。
スクリーンショット (603).png

今BoxCollionに入っているか?という判定をするためにBooleanを追加します。(名前は回復とかわかりやすいようにしておきます。)
続いてBP_ThirdPersonCharactorを開いて、プレイヤーにHPの変数をIntegerで追加します。
結果わかりやすいようにTickで数字を表示してくれるようにしました。
一回コンパイルをして、右側の詳細タブからデフォルト値を1にしておきましょう。
スクリーンショット (609).png
回復のBPの方に戻ってBPを組んでいきます。
スクリーンショット (600).png
BegenOverlapのノードのOtherActorからOverlapしてるものの情報を取ります。CastノードをOtherActorから繋げて、OverlapしてきたものがBP_ThirdPersonCharactorがあるかどうか確認します。(Castについては後に解説)BP_ThirdPersonCharactorがあったらオブジェクト変数というものに昇格(これでこのBP内でBegenOverlapが起こった後はBP_ThirdPersonCharactorの情報を取り出せる変数ノードを置けるようになります)します。
スクリーンショット (611).png
先ほど作ったBooleanをSetで配置し、Trueにします。

次にEndOverlapからもCastをだし、出ていったのがBP_ThirdPersonCharactorか確認します。BP_ThirdPersonCharactorであったらBooleanをSetで配置しFalseにします。これでBP_ThirdPersonCharactorがBocCollisionに入ったらBooleanがTrueになり、出ていったらFalseになります。

最後にTickを持ってきます。まず、ブランチを出してBooleanがTrueである(BP_ThirdPersonCharactorが入っている)か確認します。Falseだった場合この時点で処理が終了します。Trueであったら、次にHPがいくつかどうか判定します。
先ほど作ったBP_ThirdPersonCharactorの変数からコードを伸ばして「get(変数名)」と打つと、BP_ThirdPersonCharactorの中にあるHPの変数を参照することができます。
スクリーンショット (613).png
持ってきたHPの変数を条件式に入れます。
HPの変数<100という式を組むので、HPの変数からコードを伸ばし<を入力して条件式を出します。
上にHPの変数を繋げて、下の四角に100と入力しましょう。
新しいブランチノードを出して条件式の出力のBooleanを繋げます。先ほどのコリジョン内にいるかどうか確認するブランチのTrue側からノードを伸ばし繋げます。もしHPが100以上だったら回復イベントは起きないので(やらなくてもきちんと動きますが)Falseの先にSetでコリジョン内の判定Booleanを出して、Falseにしておきましょう。
ではHPが100以下だった時の処理を書きます。
BP_ThirdPersonCharactorの変数を持ってきてHPの変数をgetで出します。そこから加算ノードを出してHPの変数を上に繋げます。下の四角には1を入れます。
次にもう一度BP_ThirdPersonCharactorを出して今度はSetでHPの変数出します。Integernoのピンに先ほどの加算ノードの出力ピンを繋げ、HPの数字を判定するブランチのTrueとHPの変数のSetノードを繋げます。
コンパイルして保存し、BPをマップ上に配置しましょう。
左上のPrintstringにご注目。
noilly_magic_プレビュー__NetMode__Standalone____64-ビット_SM5__2022-07-05_03-24-05_AdobeExpress.gif

こんな感じになっていれば成功です。
Name,String,Text

スクリーンショット (615).png
Name,String,Textは文字に対応した変数です。
筆者もいまいちよくわかっていないのでざっくりとした解説になります。

詳しく説明してくださっているとんこつ様のブログ
https://shuntaendo.hatenablog.com/entry/2017/07/04/045214

Nameは文字通り、名前を指定する変数になります。
BPからboneの名前などを取りたい時に使うのがこの型です。他にもデータテーブル等扱うようになるとちょいちょい出てきます。

StringはPrintstringで使われている変数になります。
Stringは唯一BPで文字を足したり合わせたりできるらしく、主にデバッグ関連で使うことが多いです。

TextはUI等画面に表示される文字列として使われる変数です。PrintTextというノードでPrintstringと同じように画面に出したりすることができます。
(ほぼ使用用途はUI)

Vector,Rotation,Transform

スクリーンショット (616).png
Vector,Rotation,Transformは「どこで」を示す変数になります。

各変数ごとの特徴
・Vector
Vectorはx,y,z軸を使って位置やサイズを表したものになります。
位置とスケールによく使います。たまに速度とかにも。
スクリーンショット (622).png

四則演算を使うことができ、Vector同士での計算も、VectorとFlote,Integerとの計算もできます。
移動系に使うことがかなり多め。
猫でもわかる~の2のように往復する足場を作ったりできます。

・Rotation
RotationはX,y,zを軸としてどれだけ回転しているかを表したものになります。

スクリーンショット (623).png

Rotaionは四則演算ノードのうち乗算しか使用できず、且つFlote,Integerとしかできません。
代わりにRotationには専用の[Combine Rotators]というRotation専用の加算ノードがあります。
また、[Find Look at Rotation]という非常に便利なノードがあります。StartとTargetにVectorを入れると、StartのVectorのものがTargetの方向を向くのに何度回ればいいか、というのを計算してくれるというものです。
例えばStartにNPCのVector、TargetにプレイヤーのVectorを入れると、イベントが発生したタイミングでNPCがプレイヤーの方向を向く、みたいなノードを組むことができます。

・Transform

Transformは、Location(Vector),Rotation,Scale(Vector)の3つを合わせたノードになります。
スクリーンショット (624).png
Transformは直接四則演算をしたりすることができず、[Break Transform]というノードを使って3つに分解することで、計算することができます。
逆に3つの変数からTransformにしたい時はMake Transformで合成することもできます。
また、いろいろなノードでTransformの入力・出力ピンがある時、Transformのピンを右クリックして「構造体ピンを分割」を選べば分解することができます。
スクリーンショット (631).png
スクリーンショット (632).png
また、VectorやRotationも同じようにFloteまで分解することができます。
スクリーンショット (625).png

この3つの変数によく使うノードになります。
スクリーンショット (626).png
BPやコンポーネントのWolrd上(レベル上)のVector,Rotation,Transformの位置を取って来たり位置を変更するものです。
左側のGet Actor~,Set Actor~はBP全体を対象としたものになり、何も入っていない時はSelfと表示されこのノードが置いてあるBP自体が対象となります。他のBPをCastしたときの右側のピンやBegenOverlapなどから出ているOtherActorのピンを繋げることで繋げたピンに含まれているBPの位置をGetしたりSetすることができます。

右側のGet World~,Set World~はBP内に含まれているコンポーネント(StaticMashやSketalMesh、Collisionなど)のワールド上での位置を取得するものになります。
左側のノードとの違いですが前提として、ゲーム内には大きく二つの座標があります。1つがレベルが広がっているWolrdの座標です。そしてもう一つがBPのビューポート内でのローカル座標になります。
左側のノードはBPのローカル座標0.0.0がワールドにおいてどこにあるか?を取る者になります。
対して右側のノードはローカル座標1.2.3とかにあるものがワールドでどこにあるか?というものになるので「BPのワールド座標+コンポーネントのローカル座標」を足した数値になります。
ブログ用.png
(ちょっとわかりにくいけどこんな感じです)

Set~ノードのパラメーター解説

パラメーター 内容
ターゲット Setする対象
New~ 新しくSetする数値
Sweep 新しい地点までスイープして移動。途中で何かのコリジョンに当たった時停止するかどうか
Teleport 新しい地点にテレポートする。その地点に出現する感じ?

SweepとTeleportの検証
上から 変更なし、Sweep、Teleportになります。
noilly_magic_プレビュー__NetMode__Standalone____64-ビット_SM5__2022-07-08_00-07-25_AdobeExpress.gif

CastとGetActorOfClass

スクリーンショット (637).png
・Cast
Castは、左側のObjectピンに入力されたObject(ActorやPlayerPown等)がCastoto~の後に続くものと一致しているか?というのを判断するノードになります。
OverlapやHitイベントノードについているOther Actorから繋げることが多いです。このノードを繋げることによって、Other Actorの中のObjectの変数などを編集することができます。また、「カスタムイベント」というBP内で作成した独自のイベントを呼び出すこともできます。
左のObjectノードに繋げないとエラーが出ます。

・Get Actor Of Class
Get Actor Of Classは左下の「クラスを選択」で選んだクラスのobjectの情報が右のReturnValueから出力されます。
スクリーンショット (639).png
これによりCastでは必要だったOther Actor等の外部からのObject情報が無くても選択したクラスの変数などが編集できます。
スクリーンショット (641).png
(このようにCastが無くてもBP_ThirdPersonCharactorの変数を持ってこれます)

この2つのノードは大変便利なのですが、「参照連鎖」というものが起こってしまいます。

スクリーンショット (642).png

筆者が過去に作ったプロジェクトのプレイヤーBPなのですが、参照が恐ろしいことになっています。
これは左側のBPの情報を真ん中のBPがとっていて、真ん中のBPの情報を左側がとっているという感じなのですが、めちゃめちゃプロジェクトが重くなります。
右側のBPがロードされたときに真ん中と左側のノードがすべてロードされるような状態なので、プレイを押した瞬間5秒くらいフリーズしたりします。(筆者のパソコンが低スぺなのもありますが)

ので、初心者のうちは便利に使って良いですが、慣れてきたら参照連鎖を断つやり方をするようにしましょう。
一番わかりやすい方法としては「ブループリントインターフェース」というものがあります。
スクリーンショット (645).png
詳しい解説はこの記事ではしませんが、簡単に言うとCastなどで受け渡ししていたメッセージや数値を送ったり受け取ったりする専用のBPになります。
スクリーンショット (643).png
こんな感じで集約されるので、参照連鎖が広がることを避けることができます。
今すぐ知りたいという方へおすすめの動画です。

終わりに

初心者の心を失う前に書いてみました。
どれも自分がゲームを作り始めてた頃知りたかったものになります。(過去の自分に記事を投げたい)
余りにも長文なのでここで一区切りとしていますが、〆切が過ぎ去った後にSpawnActor系とかDamageとかDestroyActorとかdelayとかも書きたいですね。
ここまでお読みいただき、ありがとうございました。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?