<前文>
自作ゲームを売る
今年の目標ですが、自作したゲームを販売します。
1.良いゲームを作る
個人で作成する以上、AAAのような作品は作れません。しかし買う側からしたら個人が作成したから精度が低いとかは関係ないです。買って得したゲームにしたいです。
それで色々考えています。
- ストーリーを重視
- ゲームをプレイした人の意見を取り入れる
- ゲーム好きな人の意見を取り言える
- 佳作を目指す。満点は狙わず、及第点を狙う。
- 一点だけ凄い所を作る
1.1 ストーリーを重視
学生時代、本読むのが大好きだった私は、ストーリーを作成するのが大好きなので、この辺で他のRPGと差を出せると思います。面白いストーリーには理由があります。その辺を丁寧に整理する事で自分のゲームのストーリーを面白く出来ると思います。
1.1.1 次の町にたどり着くたびに、新しい情報を得る
ストーリーは変化です。変化は新しい情報を得る事で生まれます。
1.1.2 Character development
ユーザーが新しい情報を得る時に、ユーザーが操作するキャラもその情報を得ます。その時にそのキャラクターがどのように成長するかが、ストーリーが面白くなるかどうかの分かれ目です。
1.1.3 Character そのものの魅力
キャラが成長する前にそのキャラそのものに魅力がないとユーザーは興味を示しません。魅力的なキャラが登場する必要があります。
最近、鬼滅の刃がヒットしているらしいですが、登場するキャラの魅力が他の漫画に比べて段違いです。
1.1.4 Villain の深堀り
日本のアニメがアメリカで受けている理由の一つが、悪役が単に悪い奴でなく、もう一人の主人公である所です。Villainが何故そう言う行動を取るのかの細かい設定が大切です。
1.2 ゲームをプレイした人の意見を取り入れる
ゲームを買ってプレイしてくれた人のコメントを参考にして改良する。
1.3 ゲーム好きな人の意見を取り言える
これが大切なんですが、どうすれば意見を貰えるのか分かりません。検討中です。
1.4 佳作を目指す。満点は狙わず、及第点を狙う
バグを残して販売、他人の著作物の無断使用、などの最低限のルールを破ってしまわない様に気を付ける事。
1.5 一点だけ凄い所を作る
一点だけAAAのゲームですら出来ない凄い事をやるのだったら、materialをもっとアニメ調に変化する事とかですかね。
2. 情報ハイウェイに乗る
上記に良いゲームを作るには何が必要なのかを考察したのですが、何かが違うと思いました。そこで思いついたのがこれです。このアイデアは元々、テレビとインターネットの違いとは何なのか?を考えていて発見したのですが、かなり深堀出来そうなアイデアです。
まだどのような切り口で分析したら良いのか分かっていませんので、今回は簡単にアイデアだけを説明します。
情報ハイウェイに乗るとは、YouTubeの急上昇に載ったり、世界的なinfluencerに紹介されたりする事を指します。
ゲームを売る為には、この情報ハイウェイに乗る必要があります。しかも良い評価と共に乗る必要があります。悪い評価と共にYouTubeの急上昇に載ったらそれこそ載らない方が良かったとなります。所謂炎上というやつです。
2.1 天気予報
具体的な考えは、まだあまり発展していませんが、日本に帰って来てびっくりした事の一つが、みんなが良く天気予報を見る事でした。確かに日本では雨になると絶対に傘が必要になるので明日の天気は結構大切です。情報ハイウェイにおいて天気予報はかなり重要な位置を占めている気がしてます。
2.2 流行りに乗る事と著作権
アメリカで日本のアニメが大ブームになった時、英語圏にいた極少数のアニメの専門家は瞬く間に有名に成りました。ポケモンgoが流行った時も同じでポケモンgoについて解説するYouTuberは一気に有名に成りました。
この流行りに乗る事と情報ハイウェイに乗るはある意味同じです。しかし勝手に流行り物を自分のゲームを売るために利用したら著作権違反で訴えられてしまいます。
著作権を破る事と引用は全く違います。
簡単に言えば、誰々が著作物でこう言っていますが、私はこう思います。というのが引用です。
しかしネットの世界(日本だけでなくアメリカも)ではこれらはゴッチャにされて、地位の高い人が低い人の著作物を無断で利用する時は引用にあたり、逆の場合は著作権違反になる。と言うまるで畜生の世界のルールがそのまま、実践されています。
だからアニメの批評をするのに、そのアニメの絵を載せるのは引用であって著作権違反ではないんですが、現実では出版社の意向に沿わない批判をした場合は直ぐに著作権違反で訴えられ、本当に著作権違反かどうかも検討されない内にネットから削除されます。これは何も日本に限った事じゃなくて、アメリカでも大体同じです。最近でもあるvtuberのイラストがペドに当たるんじゃないか?と批判したYouTubeのchannelが著作権違反で一発で消されました。vtuberのイラストがペドに当たるかどうかを語るにはそのイラストを引用する必要は絶対あると思われますがお構いなしです。
この辺の事情を理解した上で、流行り物に乗りまくって情報ハイウェイに入る事が大切と考えます。
2.3 局所的に有名になる
情報ハイウェイに乗る前に、ある一部の人だけには高評価を得る。つまり局所的に有名に成る事も戦略として大事だと思います。この局所の人達に誰を選ぶのか?それを考えるのは結構難しいです。私としては日本とアメリカにいる日米のハーフやバイリンガルの人達の間で高評価を得るのがやりたいのですが、そんなネットワーク存在していませんし。プログラマーの間で高評価を得るのはかなり難しいですし。
それで思いついたのですが、近所や知り合いに売って高評価を得る。というのは結構有りかと思っています。
色々考えましたが結構方法はありそうです。それでは今週の勉強を始めます。
<本文>
今週はもっと沢山のモンスターを配置して問題を抽出します。
先週のバグについては特に今週やらないといけない部分はないと思われるのバグの直しは無しです。
1.モンスターをもっと配置してバグを見つける
以下の様に並べてみました。
単にMonsterSpawnDataを増やしただけです。
戦闘してみます。
途中で死ぬかと思ったらレベルが上がって全回復して全部の敵を倒せました。面白く無いです。ゴブリンを倒して得られる経験値を調節します。
もう一度戦ってみます。
今度は死にました。
そしたらエラーです。
これから直していきます。
戦闘で負けた時に実行するコードを以下の様に変更しました。
テストします。
簡単にテスト出来るように主人公のパラメーターをモンスターより弱くします。
エラーは出なくなりました。
しかし沢山のバグがまた出て来ました。
バグ1
戦闘で主人公が死んでいるのに復活しています。
バグ2
「もう一度始める」ボタンを押すと戦闘から始まります。戦闘前の場所から始まるべきです。
1.1 バグ1の直し
Set Anim Instance Classを外しました。
むごたらしく死んでいます。
1.2 バグ2 の直し
Game Overになると以下のwidgetが開かれるのですがどこから開いているのかが分かりません。
幾らBPを見てもわからないのでUE4C++を見たら、こっちで実装していました。
これを読むと、Widgetの方だけ変更すればバグは直せそうです。
Widget、GameOverScreenのreStartButtonをクリックした時に実行するコードを以下の様に変更しました。
テストします。
「もう一度始めるボタン」を押すとMap1の元の位置に戻って来ました。
直りました。
1.3 GameOverScreenのデザインの改良
GameOverScreenに、少なくとも「止める」「スタート画面に戻る」ボタンの追加は必要だと思います。
以下の様に作り直しました。
UIのみ操作出来る様にSetInputModeUIOnlyを追加しました。
SetInputModeUIOnlyを追加しましたが、このやり方が正しいのか正直覚えていません。戦闘画面に入るとcharacterの操作は全く出来ませんが、その時にSetInputModeUIOnlyを使用している形跡が全く無いです。後でもう一度この事は調べます。
「もう一度始めるボタン」の実装は以下の様にしました。
特に記述する事はありません。前の実装ではExecute Console Commandを使用していました。
「ゲームの終了ボタン」は以下の様に実装しています。
QuitGameを使用するのは初めてです。使用方法に特に気を付ける事は無いはずです。
「スタート画面に戻るボタン」の実装は以下の通りです。
RPGGameInstanceに保持しているデータは全て消す必要があると考えていますが、後でその辺は直します。
テストします。
即興で作成した割には中々いい感じです。
この画面でキャラを操作しようとしましたが動きません。SetInputModeUIOnlyを使用するのが正しいやり方なのか一寸覚えていませんが、目的は達せられています。
「もう一度始めるボタン」をクリックします。
戦闘が始まる前に戻って来ました。
セーブポイントを作成したら、その場所からやり直すようにしたいです。
「ゲームの終了ボタン」を押したら、ゲームが終了しました。
「スタート画面に戻るボタン」を押したらゲームの最初に戻りました。
スタート画面のボタンは新しく始める以外は適当にしか作成していないので、後でこれらも直します。
2. 更なるバグの発見
更にバグを見つけるために配置したモンスターを倒していきます。
2.1 向きの保持
戦闘画面から頻繁に元のマップに戻ってくると酔い易くなっている事に気が付きました。
2.2 戦闘が永遠に終わらないバグ
プレイヤーが操作するキャラがすぐ負けてしまうので、武器と防具を装備させて戦闘に参加したら、お互いの防御力が互いの攻撃力を上回り、お互いにダメ―ジが与えられなくなりました。
戦闘が終わりません。
2.3 拾えるアイテムは(!!)表示を追加
戦闘システムのバグではありませんが、NPCとの会話の様に、拾えるアイテムは(!!)で知らせてほしいです。
(!!)をアイテムに追加します。
2.4 徘徊するモンスター用の別なAIが必要
プレイヤーの操作するキャラがモンスターが動ける領域に侵入すると、全てのモンスターが、プレイヤーの操作するキャラ目がけて追いかけて来ます。
非常に単調な動きで、不自然に感じます。
2.5 待ち伏せするモンスターの作成
ある領域に侵入するとモンスターが出現するパターンも面白いと思います。
2.6 武器を装備した状態で戦闘開始したらアニメーションが…
武器を装備した状態で戦闘開始したらアニメーションが最初の戦闘の時だけ武器持ちのアニメーションで、2回目から武器なしのアニメーションになってしまいました。
正直、こんなに沢山のバグが見つかってショックです。バグ出しに挑戦して良かったです。
3. バグだし条件の設定
プレイヤーの操作するキャラのパラメーターの値を変えて、8体のモンスターと戦う事で、バグを見つけようと思います。
3.1 魔法使い的なパラメーター
プレイヤーの操作するキャラのパラメーターの値を、魔法中心で戦う事を強いられる値に変更しました。
一体倒すと、HPが40、MPが70、そして金貨が110になっていました。
因みにポーズ画面を押すとモンスターの追跡も止まっていました。
MPは70も残っていますが、HPは40しかありません。道具屋に行って回復薬を買えるだけ買って残りのモンスターと戦う事にします。
アイテムの回復薬を使用した後に、ゴブリンの攻撃を受けたら、アイテム使用時用のコメントが表示されました。
一個バグが見つかりました。
一応、8体全部倒せました。しかし持っていた金貨100枚が0になってしまいました。
ゲームを終了したらエラーが出ていました。
戦闘中に流しているBGMを保持しているはずのBattleBGMに値が無いと言っているみたいです。
これは多分ですが、戦闘中、ほったらかしてブログを書いていたら戦闘BGMの演奏が終わったので、勝手に消滅してしまったと思われます。
確認します。
戦闘BGMが終了する前に戦闘が終了した時は、ゲームを終了してもさっきのエラーは出て来ません。
今度は戦闘BGMが終了するまでほっときます。
エラーが出ました。
エラーの内容は微妙に違いますが、同じ個所です。これだけは今直してしまいます。
元の音源のLoopingにチェックを入れます。
これで戦闘中に戦闘BGMが終了する事はないはずです。
テストしてみます。
戦闘中にして、10分位別な作業していましたが、戦闘BGMが続いていました。戦闘終了後にゲームを終了してもエラーは出ませんでした。
直りました。
3.2 初級者的なパラメーター
今度はMMPを20まで下げてみました。
これでテストしてみます。
最後の2体が倒せずに死んでしまいました。
ゲームオーバーの時は、専用の音楽がほしいですね。
特にバグは見つかりませんでしたが、モンスターやプレイヤーが操作するキャラのパラメーターの調節は、ゲームの面白さに直結する事が分かりました。
3.3 ギリギリモンスターに勝てない位のパラメーター
やっぱり最初はモンスターにぎりぎり勝てない位が良い気がします。以下のパラメーターで試してみます。
一体も倒せず負けました。
現在は負けてもペナルティが一切ないので何か作成したいです。
落ちている剣を拾って装備しました。
その状態で戦ったらギリギリ勝てました。
一回死んでからアイテムが置いて在る場所に戻ると、既にアイテムを取ったにもかかわらず新しいアイテムが置いて在りました。
これも後で直します。
特に新しいバグは見つかりませんでした。
3.4 プレイヤーが操作するキャラのパラメーターの調節で分かった事
最初はモンスターが倒せない位で、短剣を装備したらギリギリ一体倒せる位、更に盾を装備する事で、沢山のモンスターと戦えるのが最適な値と感じました。これを達成する為にはもはやゲーム一部を作成するだけでなくゲームそのものの作成が必要と思いました。
回復薬ですが、戦闘後に使用するには有効ですが、戦闘中に回復薬を使用しても意味がないです。これはこれで面白いと思いました。
4. バグの直し
これまでに以下のバグが見つかりました。
- 戦闘画面から戻って来た時に向きが変わっている。
- 戦闘が永遠に終わらない時がある。
- 拾えるアイテムにも(!!)表示を追加
- 徘徊するモンスター用に別なAIを作成
- 待ち伏せするモンスターの作成
- 2回目から武器なしのアニメーションになるバグの直し
- 戦闘中にアイテムの回復薬を使用した場合、次の攻撃の後にもアイテム使用時用のコメントが表示されるバグ
- 同じアイテムが何回も取れるバグ
これらのバグを直していきます。
4.1 戦闘画面から戻って来た時に前と同じ向きにする
まず、戦闘が始まった場所をどうやって保持しているのかを確認します。
モンスターの領域にプレイヤーが操作するキャラが侵入するとRPGGameModebaseBPにあるdispatcherのCallCombatBeginがcallされます。
RPGGameModebaseBP にあるCombat BeginはMap1上で以下のコードにbindされています。
この時にRPGGameInstaceBPにある変数、Third Person Character Locationにプレイヤーが操作するキャラの現在の位置が保持されます。
取りあえずここまでRotationも同じように作成します。
RPGGameInstaceBPに、Third Person Character Locationにプレイヤーが操作するキャラの現在の回転を保持するための変数、ThirdPersonCharacterRotationを作成します。
Combat Beginの実装部にこの変数に、プレイヤーが操作するキャラの現在の回転値をコピーさせます。
これで戦闘画面に移動する前のプレイヤーが操作するキャラの向きは保持されました。
その値は、もう一度Map1が開かれた時に読み込まれていたので、その時に一緒にプレイヤーが操作するキャラの向きが読み込まれるようにしました。
テストします。
キャラクターの向きは直っていましたが、カメラがキャラクターを向いています。
その結果、カメラを一回転する必要が出て来て、結局酔います。
色々弄りましたが、カメラの位置の直し方が分かりませんでした。今回はここまでとしてカメラの位置の直しは後でやる事にします。
4.2 戦闘が永遠に終わらない時がある。
お互いの防御力が攻撃力より高い場合、ダメージを与える事が出来ないので永遠に戦闘が続きます。
これは「逃げる」ボタンが機能すれば解決します。
逃げるが成功するためにはCharacterのLuckが敵のLuckより上である必要があります。
取りあえず、以下の様に設定を変更してLuckの値が同じならば逃げる事が出来る様にします。
テストします。
逃げれましたが以下のようにエラーが大量に発生しました。
以下の実装部のSetVolumeMultiplierがEmptyと言っています。
調べて見たら、DownVictoryMusicを戦闘から逃げた時もtrueにセットしていました。
直します。
テストします。
今度はエラーが無くなりました。
Luckが敵のモンスターより低い場合でも30%の確率で逃げ出せるようにしました。
これで逃げるボタンを押し続ければいつかは戦闘から逃げ出せるように成ったはずです。
テストします。
敵のモンスターのLuckをプレイヤーが操作するキャラよりも高く設定しました。
ひたすら、戦闘から逃げたら4回目くらいで逃げれました。
4.3 拾えるアイテムにも(!!)表示を追加
まず、NPCにどうやって(!!)を追加したのか確認します。
TextRenderを使用しています。
TextRenderのvisibilityは以下の方法でオンオフされています。
結構複雑な仕組みをしています。
思い出してきました。最初、Box内に侵入したらTextRenderのvisibilityをオンにセットしていたのですが、この方法だと全部のNPCのtextRenderがOnになってしまったんです。それで上記のような方法を採用したんでした。
ただこの方法だと、まだ一つ一つのinstanceまでは区別出来ないので、以下の方法でやる事にします。
まず、RPGGameModebaseBPにこれから拾うアイテムの名前を保持する変数を作成します。
次に、DroppedItemBase内にそれぞれのインスタンスの名前を保持するための変数、ItemNameを作成します。
このItemNameはInstance Editableにしてそれぞれのinstanceで違う名前が持てるようにします。
更に、TextRenderとPointLightをDroppedItemBaseに追加します。
プレイヤーが操作するキャラがボックス内に侵入したら、そのボックスが属しているDroppedItemBaseのインスタンスが持つItemNameの値、つまり名前を、RPGGameModebaseBPのItemNameにコピーします。
勿論、プレイヤーが操作するキャラがボックス外に出た時は、RPGGameModebaseBPのItemNameにNoneをセットする事で、それまでセットされていた名前を消します。
そして、RPGGameModebaseBPのItemNameにセットされている名前とプレイヤーが操作するキャラが侵入しているboxが属しているDroppedItemBaseのインスタンスが持つItemNameの名前が一致しているか確認します。
一致した場合は、設置したPointLightとTextRenderが表示されます。しない場合は表示されません。
これで放置されているアイテムが拾える場合は、そのアイテムの上に(!!)が表示されるはずです。
テストしてみます。
(!!)マークが表示されました。きちんと剣だけ表示されています。隣の盾には(!!)マークは表示されていません。
念のために、隣に移動して見ると今度は盾の上に(!!)が表示されました。そして剣の上の(!!)は消滅しています。
出来ました。
4.4 徘徊するモンスター用に別なAIを作成
現状では、全てのモンスターは、プレイヤーが操作するキャラが、NavMeshBoundsVolumeが指定した範囲内に侵入した途端、全力でそのキャラを追いかけるだけです。持ち場を設定してその範囲内に、プレイヤーが操作するキャラが侵入した時だけ追いかけるようなAIを作成したいです。
つい最近UE4のAIの勉強をやったのに既にやり方を忘れてしまいました。やる内容が大量にありそうなので、この部分は別に枠をとって後でやる事にします。
4.5 待ち伏せするモンスターの作成
ある場所にプレイヤーが操作するキャラが侵入したらモンスターが突然発生しだすトラップ的な物を作成したいです。
以下の様に作成しました。
MonsterTrapの方ですが、Boxを追加しただけのActorです。
このBox内にプレイヤーが操作するキャラが侵入したら以下のコードによってモンスターが発生します。
突然、モンスターが発生するとユーザーが混乱するかもしれないので、以下のwidgetも追加しました。
テストします。
以下の様にモンスターが現れました。結構急に出て来ます。
これでOKとします。
4.6 二回目から武器なしのアニメーションになるバグ
これは一番直さなければならないバグです。
原因が分かりました。
PlayAnimationノードを使用しているため、いつも使用しているMyThirdPerson_AnimBPを一端外している様です。そのためMyThirdPerson_AnimBPの変数であるWithWeaponの値が消滅してしまったようです。
この事からキャラのアニメーションはAnimBPで一括して管理した方が良くPlayAnimationノードの使用は中止した方が良いと思われます。
ただし、この理論が正しいかの確認をするために、一端、以下に示したコードを戦闘で武器を装備した状態で攻撃をした後に追加しました。
これでテストします。
出来ています。
理論は正しい様です。
PlayAnimationノードの使用は中止してキャラのアニメーションはAnimBPで一括して管理する。これも結構な量になりそうなので別に枠をとって後でやります。
4.7 戦闘中にアイテムの回復薬を使用した場合、次の攻撃の後にもアイテム使用時用のコメントが表示されるバグ
理由が分かりました。
プレイヤーが操作するキャラがアイテムを選択すると対戦しているモンスターの選択も自動的にアイテムになってしまっています。
以下の方法で直しました。
Itemを選択したと判断されてもその後で、プレイヤーが操作するキャラかモンスターを検査します。モンスターの場合はAttackと同じセリフになるようにします。
テストします。
プレイヤーが操作するキャラがアイテムを使用した後に、モンスターが攻撃した時も正しいセリフが選択されています。
直りました。
4.8 同じアイテムが何回も取れるバグ
4.8.1 BPを使用してアイテムを動的に生成する
現状、マップ内に直接Instanceを配置したケースしかないので、BPで動的に作成したItemをマップ内に配置出来る様にします。
まず、Dropped Item Baseを作成するためには、最低でも以下のパラメーターが必要です。
それで以下のStructureを作成しました。
そのStructureをタイプとしたArray、ItemSpawnDataをRPGGameInstanceBPに作成しました。
試しに2つほど要素を作成しておきます。
今度はmap1内でSpawnItemsと名付けた関数を作成します。この関数はItemをSpawnするための関数です。以下に実装部を示します。
Map1のEventBeginPlay関数でこの関数を呼び出します。
テストします。
Itemは出来ています。
BPを使用してItemを動的に生成する事が出来ました。
4.8.2 収得したアイテムが二度と生成されないようにする。
PickUpItemウィジェットに以下の関数を作成します。
この関数を「拾う」ボタンが押された時に実行すれば、そのボックス内にあったアイテムは二度と生成されなくなるはずです。
テストしてみます。
アイテムを拾った後、戦闘を行い、map1に戻って来ました。拾ったアイテムがある位置に行ってみるとその場所にあったアイテムは生成されていませんでした。
一応、完成です。
5.まとめと感想
今週はここまでとします。
今年は、正月返上でやろうとしたのですが、結局休んでしまいました。だから今回は2週間分まとめてブログに載せています。