UE4の勉強記録

UE4の勉強の記録です。個人用です。

「Unreal Engine4.xを使用してRPGを作成する」の足りない部分を作成する。レベルデザインをする2

<前文>

f:id:kazuhironagai77:20191027202819p:plain

最近、C++の復習をしていてmove constructor を勉強したのですが、はっきり言ってmove constructorそのものを、今まで知らなかったです。

知らなかったのはしょうがないので、勉強するしかないですが、勉強したらRvalueとLvalueを理解していないと、move constructorが理解出来ない事に気が付きました。

流石にRvalueとLvalueは理解しているからと教科書を読み続けたら、どうしても分からない。何を言っているのか分からなくなってしまいます。

ひょっとするとRvalueとLvalueも勘違いしている部分があるのかもしれないと、調べて見たら間違って理解していました。

私はRvalueの値はレジスターか何か、アドレスがない場所に一時的に保存されていて、アドレスのあるメモリーには保存されていないと思っていたのですが、Rvalueの値も一時的とは言えアドレスのあるメモリー上にしっかり保存されるようです。ここを理解したらmove constructorが何を行っているのかもしっかり分かりました。

分からない事が分かるようになるのは楽しいです。

それでは、今週もUE4の勉強をしていきましょう。

<本文>

今週は、先週勉強したFast Travel Within A single Level and Multiple Levels - (UE4)をCh2に実装します。

<方法と結果>

0.地図と2つのボタンの絵を用意する。

2つのボタンは先週作成したものをそのまま使用します。地図は今描いた物を使用します。

f:id:kazuhironagai77:20191103210633p:plain

ちょっといい加減ですが、ゲームのコンセプトが決まっていないのでしょうがないです。

1.2つのenumを作成する

f:id:kazuhironagai77:20191103210708p:plain

しました。Mapの方だけ中身も作成しました。

f:id:kazuhironagai77:20191103210736p:plain

2.3つのマップを作成する。

まず、Map1を作成します。

f:id:kazuhironagai77:20191103210804p:plain

f:id:kazuhironagai77:20191103210813p:plain

こんな感じです。

Map2とMap3も作成しました。

f:id:kazuhironagai77:20191103210833p:plain

f:id:kazuhironagai77:20191103210842p:plain

3.WayPointアクターを作成する。

f:id:kazuhironagai77:20191103210905p:plain

出来ました。話は変わりますが、

f:id:kazuhironagai77:20191103210926p:plain

この目を開く意味は、エディターから値を変換できると言う意味だそうです。

f:id:kazuhironagai77:20191103211007p:plain

本当にエディターから編集が出来ますね。

長年の謎が解けました。

4.GameInstanceを作成する。

ここからが、問題です。Ch2のGameInstanceはRPGGameInstanceでUE4C++で作成されています。しかしここで使用するGameInstanceはBPで新しく作成してます。

1.UE4C++でBPに書かれている内容をRPGGameInstanceに書く。

2.新しくBPでGameInstanceを作成してRPGGameInstanceの内容をBPで書く。

3.RPGGameInstanceからBPを派生してそのBPをGameInstanceに使用する。

が方法として考えられます。

しかし最初にする事は、Ch2のコピーを作成する事ですね。失敗してもやり直しが出来ますから。

私は一人で作成する事が好きなので、今までGitHubは使用しませんでしたが、こうなるとGitHubの使用も考える時なのかもしれません。時に無料でprivate repositoryが使用出来る今はGItHubに上げてもデメリットもありませんし。

f:id:kazuhironagai77:20191103211406p:plain

取りあえず、今回はコピーを作成するだけにします。

1から3ですが、もう3しか考えていません。まずこれから試してみます。

f:id:kazuhironagai77:20191103211506p:plain

作成しました。

f:id:kazuhironagai77:20191103211525p:plain

MyRPGGameInstanceBPをGame Instance Classにセットします。

まず、テストしてみます。RPGGameInstanceには、以下に示すように3つの変数があり、

f:id:kazuhironagai77:20191103211605p:plain

それぞれ値を保持しています。これらの値がBPでも保持されるのならまずは、大丈夫でしょう。

PartyMemberからみていくのが筋ですが、PartyMemberが今は一人しかいないのでテスト出来ません。

GameGoldの値を見てみます。

f:id:kazuhironagai77:20191103211639p:plain

最初は10です。

ポーションを買ったら、20になりました。

f:id:kazuhironagai77:20191103211702p:plain

どうやら、ポージョンの値段を‐10に設定していたみたいです。

お店から離れて、インベントリーを開きましたが、20のままです。

f:id:kazuhironagai77:20191103211730p:plain

大丈夫そうですね。

よしこれでやってみます。

Zoneのenumの値を追加します。

f:id:kazuhironagai77:20191103211800p:plain

最後にGameInstanceに変数を追加します。

f:id:kazuhironagai77:20191103211824p:plain

うーん。これくらいだったらUE4C++で作成出来たかもしれませんね。

4.地図を表示する。

UIフォルダー内にWidget Blueprintから

f:id:kazuhironagai77:20191103212354p:plain

Widgetにさっきの絵とボタンを追加。

f:id:kazuhironagai77:20191103212420p:plain

一周回ってこの絵も良く見える気がしてきた。

ここからThirdPersonCharacterBP内でキーボートを押したら地図が表示されるようにコードを実装するのですが、インベントリーから呼ぶ方が良い気もします。ただこれは別の場所へのワープも兼ねているので、キーボートから呼び出しても良い気もします。

取りあえず、今はチュートリアルの通りに作成します。

チュートリアルではThirdPersonCharacterBP内で実装していますが、Ch2内ではFieldPlayerがプレイヤーのキャラクターなので、FieldPlayer内に実装します。

f:id:kazuhironagai77:20191103212501p:plain

テストします。

f:id:kazuhironagai77:20191103212527p:plain

f:id:kazuhironagai77:20191103212538p:plain

正常に動作しました。

このチュートリアルでは、ゲームをプレイしている時に必要でない時は絶対マウスを表示しないように設定しているのですが、そんなにそれって絶対必要なのでしょうか?

f:id:kazuhironagai77:20191103212617p:plain

f:id:kazuhironagai77:20191103212626p:plain

結局この二つの関数もそのために使用している訳ですし。まあ、消えていたほうが綺麗なのは間違いないですね。

5.GameInstanceにカスタムイベントを2つ作成する。

前回と全く同じ様に作成しました。

全く同じなので図も省略します。

6.MapWDのボタンに機能を追加する。

これも全く同じなのですが、以下の部分だけFieldPlayerのBeginPlay関数の後に追加しました。

f:id:kazuhironagai77:20191103212729p:plain

テストします。

f:id:kazuhironagai77:20191103212748p:plain

テレポートは出来たのですが、スタート画面に戻ってしまいました。これは後で直します。

7.マイナーなミスを直す。

直しました。

<テスト>

Map2にWayPointを追加してテストします。

f:id:kazuhironagai77:20191103212829p:plain

こちらもスタート画面に戻ってしまいました。

<直し>

まず、スタート画面が一々表示されないようにします。

f:id:kazuhironagai77:20191103213009p:plain

この関数がレベルが新しくなるたびに呼び出される訳です。それでスタート画面が毎回表示されるみたいですね。

スタート画面はゲームを始める最初の一回のみ呼ばれればいいので、GameInstanceクラスにbool変数を作成し、最初のみtrueを返すようにします。

f:id:kazuhironagai77:20191103213030p:plain

GameInstanceのヘッダーにbool変数であるisStartScreenを宣言しました。IsInitializedというbool変数が丁度宣言した真上にありましたので、これを真似て作成する事にします。UPROPERTYは取りあえず使用しないで作成してみます。

Getter とSetterを作成します。

f:id:kazuhironagai77:20191103213109p:plain

コンストラクター内で初期化します。

f:id:kazuhironagai77:20191103213131p:plain

実装します。

f:id:kazuhironagai77:20191103213226p:plain

GameModeクラスのBeginPlay()関数内から呼び出します。

f:id:kazuhironagai77:20191103213311p:plain

これで、最初の一回だけスタート画面が表示されるはずです。

まず、ビルドしてみます。

f:id:kazuhironagai77:20191103213358p:plain

成功しました。

それではテストしてみます。

f:id:kazuhironagai77:20191103213422p:plain

ゲームを開始しました。スタート画面は表示されています。

f:id:kazuhironagai77:20191103213446p:plain

違うマップにテレポートしましたがスタート画面は表示されません。

f:id:kazuhironagai77:20191103213506p:plain

もう一度、ゲームを開始した場合は、スタート画面は表示されます。

どうやら成功みたいです。

<おまけ>

Map3にテレポートするボタンも作成します。

f:id:kazuhironagai77:20191103213529p:plain

マップを上に示すように変えました。

マップ上のXYZをクリックすると

f:id:kazuhironagai77:20191103213558p:plain

Map3にテレポートします。

<まとめと感想>

今週はちょっと短いですがこれで終わりです。