<前文>
最近、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つのボタンは先週作成したものをそのまま使用します。地図は今描いた物を使用します。
ちょっといい加減ですが、ゲームのコンセプトが決まっていないのでしょうがないです。
1.2つのenumを作成する
しました。Mapの方だけ中身も作成しました。
2.3つのマップを作成する。
まず、Map1を作成します。
こんな感じです。
Map2とMap3も作成しました。
3.WayPointアクターを作成する。
出来ました。話は変わりますが、
この目を開く意味は、エディターから値を変換できると言う意味だそうです。
本当にエディターから編集が出来ますね。
長年の謎が解けました。
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に上げてもデメリットもありませんし。
取りあえず、今回はコピーを作成するだけにします。
1から3ですが、もう3しか考えていません。まずこれから試してみます。
作成しました。
MyRPGGameInstanceBPをGame Instance Classにセットします。
まず、テストしてみます。RPGGameInstanceには、以下に示すように3つの変数があり、
それぞれ値を保持しています。これらの値がBPでも保持されるのならまずは、大丈夫でしょう。
PartyMemberからみていくのが筋ですが、PartyMemberが今は一人しかいないのでテスト出来ません。
GameGoldの値を見てみます。
最初は10です。
ポーションを買ったら、20になりました。
どうやら、ポージョンの値段を‐10に設定していたみたいです。
お店から離れて、インベントリーを開きましたが、20のままです。
大丈夫そうですね。
よしこれでやってみます。
Zoneのenumの値を追加します。
最後にGameInstanceに変数を追加します。
うーん。これくらいだったらUE4C++で作成出来たかもしれませんね。
4.地図を表示する。
UIフォルダー内にWidget Blueprintから
Widgetにさっきの絵とボタンを追加。
一周回ってこの絵も良く見える気がしてきた。
ここからThirdPersonCharacterBP内でキーボートを押したら地図が表示されるようにコードを実装するのですが、インベントリーから呼ぶ方が良い気もします。ただこれは別の場所へのワープも兼ねているので、キーボートから呼び出しても良い気もします。
取りあえず、今はチュートリアルの通りに作成します。
チュートリアルではThirdPersonCharacterBP内で実装していますが、Ch2内ではFieldPlayerがプレイヤーのキャラクターなので、FieldPlayer内に実装します。
テストします。
正常に動作しました。
このチュートリアルでは、ゲームをプレイしている時に必要でない時は絶対マウスを表示しないように設定しているのですが、そんなにそれって絶対必要なのでしょうか?
結局この二つの関数もそのために使用している訳ですし。まあ、消えていたほうが綺麗なのは間違いないですね。
5.GameInstanceにカスタムイベントを2つ作成する。
前回と全く同じ様に作成しました。
全く同じなので図も省略します。
6.MapWDのボタンに機能を追加する。
これも全く同じなのですが、以下の部分だけFieldPlayerのBeginPlay関数の後に追加しました。
テストします。
テレポートは出来たのですが、スタート画面に戻ってしまいました。これは後で直します。
7.マイナーなミスを直す。
直しました。
<テスト>
Map2にWayPointを追加してテストします。
こちらもスタート画面に戻ってしまいました。
<直し>
まず、スタート画面が一々表示されないようにします。
この関数がレベルが新しくなるたびに呼び出される訳です。それでスタート画面が毎回表示されるみたいですね。
スタート画面はゲームを始める最初の一回のみ呼ばれればいいので、GameInstanceクラスにbool変数を作成し、最初のみtrueを返すようにします。
GameInstanceのヘッダーにbool変数であるisStartScreenを宣言しました。IsInitializedというbool変数が丁度宣言した真上にありましたので、これを真似て作成する事にします。UPROPERTYは取りあえず使用しないで作成してみます。
Getter とSetterを作成します。
コンストラクター内で初期化します。
実装します。
GameModeクラスのBeginPlay()関数内から呼び出します。
これで、最初の一回だけスタート画面が表示されるはずです。
まず、ビルドしてみます。
成功しました。
それではテストしてみます。
ゲームを開始しました。スタート画面は表示されています。
違うマップにテレポートしましたがスタート画面は表示されません。
もう一度、ゲームを開始した場合は、スタート画面は表示されます。
どうやら成功みたいです。
<おまけ>
Map3にテレポートするボタンも作成します。
マップを上に示すように変えました。
マップ上のXYZをクリックすると
Map3にテレポートします。
<まとめと感想>
今週はちょっと短いですがこれで終わりです。