第4回のUE4ぷちコンでは4作を応募させていただきました。
動画と実行ファイルはそれぞれこちらです。
Dodge Balls!!!
https://www.youtube.com/watch?v=h1t7uisGGJU
https://dl.dropboxusercontent.com/u/39588440/DodgeBalls.zip
アストロロボ・SSK
https://www.youtube.com/watch?v=C5wAsn7uMBk
https://dl.dropboxusercontent.com/u/39588440/AstroRoboSSK.zip
まもれ!アストロロボ・SSK
https://www.youtube.com/watch?v=g890GLmqmrY
https://dl.dropboxusercontent.com/u/39588440/MamoreSSK.zip
早撃ち アストロロボ・SSK
https://www.youtube.com/watch?v=Eg8GYHsgES4
https://dl.dropboxusercontent.com/u/39588440/HayauchiSSK.zip
応募順に並べていますが、実際に作成した順番は上から3, 1, 2, 4という順番です。
開発期間も作成順番が早いほど長くなっていて、アストロロボ・SSKが実質1週間くらい、まもれ!が3~4日、Dodgeが1日、早撃ちが半日くらいです。
早撃ちは6時間弱で作っているので半日もない計算ですが、とりあえずこの程度であれば短時間で作ることは可能なわけです。
今回のぷちコンでは前回と同様に自分なりの目標を立てました。
目標は3つ。
1. 完成品のみ応募する
2. Substance系のツールを使用する
3. 複数作品(2作品以上)を応募する
1はどの段階で完成品とするかという問題はありますが、ゲームの面白さとかバランスとかはある程度あればOKという感じで、タイトルからゲームを初めてゲームオーバーになってタイトルに戻る、という流れがちゃんと出来てればOKとしました。
ゲームの面白さは追求していませんが、最低限これはゲームです、といえるものを作りました。
バランスもゲームにならないバランスでは困るので、最低限のバランスは取ったつもりです。
2はSubstance DesignerとSubstance Painterを使用することを目標にしました。
実際、プレイヤーキャラのSSKや敵モデルのテクスチャにはSubstance Painterを使用していますし、ドッジボールのテクスチャやタイトルのSSKの文字などにSubstance Designerを使っています。
SDで作ったマテリアルをSPで使いたいとも思っていたのですが、そこまではまだアーティストらしい事ができないので断念。
3は4作出したのでOK。
というわけで、ちゃんと目的は達成しました。
これは素直に嬉しいことです。
しかしながら、やはり問題や反省点も多く、主な反省点は複数作品作るために1つの作品に時間をあまりかけられない→あまり新しいことはしないで知っていることを中心にやろう、となってしまった部分でしょう。
次回は出来れば、この機能使ったことないな、という物を使ってみたいな、と思います。
ここからは今回のぷちコンでの具体的な反省点、やったこと、疑問に思ったことなどを適当に列挙していきたいと思います。
順番とかもなく思いついた端から書いていきます。
1. 同じアセットを並行したプロジェクトで使用する場合の運用
今回はSSKとまもれ!SSKが同時並行して制作されており、ここで使用するアセットの一部(プレイヤーキャラのメッシュとテクスチャ)が共有されてました。
最初は適当に作った仮モデルを使っていたのですが、アーティストさんに作成してもらったメッシュを受け取った時にこれを両プロジェクトに反映するのに少々手間どいました。
仮モデルは自分が何も考えずに作ったもので、本番データとは骨構造も一致してない→AnimBP作り直し→それに合わせて色々修正ということを行う必要がありました。
それも2つのプロジェクトで。
もちろん、片方のプロジェクトで作成した後にもう片方に移行することで対応しましたが、もうちょっと楽に共有する方法はないものかなぁ、と思った次第です。
マテリアルデータベースを使って複数タイトルで使用するような場合も、データベースを更新したらそれぞれのプロジェクトで再インポートしないといけないのかな?と思うのですが、何かいい手があるんでしょうかね?
2. オブジェクトチャンネルを変更すると挙動が変わる?
今回はプレイヤーキャラ用のオブジェクトチャンネルとしてSSKというチャンネルを用意しました。
各種衝突応答の設定は正しく行ったつもりだったのですが、何故かプレイヤーキャラが壁をすり抜ける現象が発生。
オブジェクトチャンネルをPawnに変更すると正しく動いたので、衝突応答の設定が悪いのかと見直したのですがやっぱりうまくいかず。
結局Pawnに設定して対応したという経緯があります。
また、まもれ!SSKを作成している際に、チャンネルがPawnの時とSSKの時でプレイヤーキャラのスタート位置が変わるという現象もありました。
もちろん、PlayerStartの位置は変更していません。
単純に自分のミスの可能性もありますが、オブジェクトチャンネルごとに処理を変えている部分が内部的にあるかも?
3. ActorBPの継承はデメリットが多い
ActorBPを作成する場合、コンポーネントを持つ形で作成して継承は極力使わないほうが無難です。
しかし、必ず持っているコンポーネントが複数あり、一部の処理が共通化可能なため、今回は敵の作成にEnemyBaseというBPを基底に置くことにしました。
このBPを継承して3種類の敵キャラを作成しています。
残念ながら、この判断はミスだったかな、と今は思っています。
3種類くらいならコンポーネントを追加するのも苦じゃないし、共通化可能な処理も最終的にはそれほど大きなものになりませんでした。
逆に継承によるデメリットを受ける結果になってしまった気がします。
特に問題があったのはSetActorLocationのSweepをTrueにした場合の衝突応答。
EnemyBaseではSceneComponentを基底に置いておくだけで、カプセルや球などの衝突応答を行うためのコンポーネントはそれぞれの敵BPで置くようにしようと考えました。
しかし、移動時の衝突応答はルートのコンポーネントで行われるらしく、継承した関係からルートにカプセルコンポーネントなどを置くことが出来ずに衝突が取れない状態に。
最終的にはEnemyBaseのルートコンポーネントをカプセルコンポーネントにして対応。
どの敵もカプセルで衝突取れば問題なかったから良かったけど、そうでない場合は継承では対応できませんね。
4. 何故かMovementComponentを自作し、MoveToも自作
なぜそんな面倒なことを?と言われそうですが、自分でもいまいち理由不明。
最初はAIも含めてもう少し挙動を詳しく知りたい、みたいな感じで始めたんですが、最終的にはある行動が完了するまで待つ処理をどう作るべきか、という部分にシフトしたような気がします。
まず、UMovementComponentを継承したBPコンポーネントは作成できない事が発覚。
C++でなら継承できますが、BPコンポーネントではベースコンポーネントの候補に出てきませんでした。
結局ActorComponentを元にして作成しましたが、そのために普通のMovementComponentとしては使えませんでした。
MoveToは移動の目的地を設定し、そこまで移動したら次のタスクへ進むというAIタスクです。
Characterアクターなんかを使えばそのまま使えるんですが、前述の理由からMovementComponentとしては使えないMovementComponentを作ってしまったために利用できませんでした。
そのため、このタスクについても別の手法で実装を行いました。
まず、このタスクは移動終了を検知しなければなりません。移動が終了した段階でタスクは終了です。
そして移動自体を行う必要があります。しかしこれはTickのDeltaSecondsを必要とします。
方法としては、Tick時のDeltaSecondsをアクターに保持しておき、これをAIタスクで利用するという方法ですが、今回はその方法は取っていません。
今回は移動自体はアクターのTick処理で、目的地の設定と終了検知はAIタスクでやっています。
AIタスクの該当処理部分はこんな感じ。
EnemyBaseから次に進むWayPointの座標を取得、MoveToDestination命令で目的地への移動処理を設定します。
目的地に到達している場合は IsMoving にFalseが返ってくるので、これがFalseになったらAIタスクは終了へ向かいます。
IsMoving がTrueの場合は0秒Delayを噛ましてMoveToDestinationまで戻ります。
Delayを噛ましておくと1フレーム先に進むので、アクターのTick処理も動いて無限ループにはならないようになっています。
この手法はけっこういろんな場所で使いましたが、複数フレームにまたがる処理の終了を待つ、という処理の実装としては正しいのかどうか不明です。
でもまあ、便利な処理なのは間違いないですね。
5. クックしたら初期値が無視された
ゲームをクックして動作確認していたら、何故か敵が動かなくなっていた。
デバッグプリントを駆使して調べてみると、自作MovementComponentの加速度パラメータが敵アクターごとに初期値を入れていたのが無視されてるっぽかったです。
MovementComponent自体の加速度の初期値は 0 で、この場合は確かに移動しません。
しかし、敵のアクターではそれぞれで初期値を設定するようにしていて、PIEではちゃんと動いていました。
クックした場合に限り、この初期値が無視されて、MovementComponentの初期値が使われていました。
結局、敵アクターのConstruction Scriptで設定するようにしたらうまくいったのですが、なんか納得いかない…
6. ゲーム的に使うには大気フォグは使いにくい
背景を作成した段階で、プレイヤーキャラや敵キャラが背景に溶け込んで見えにくくなる現象が発生。
ライティングとかを駆使してなんとかなるかと思ったけどなんともならなかったのでフォグで対応することに。
しかし、大気フォグではここからここまでを白くフォグがかかってるようにしたい、という要望を満たせなかったので、結局はポストプロセスで対応しました。
ポスプロで深度をチェックして、というやり方なので半透明には使いづらいのですが、幸い半透明オブジェクトはあまりなかったのでそれほど問題になりませんでした。
7. AnimBPを使わないとSpawn時にTスタンスのキャラが一瞬見える
早撃ちSSKではAnimBPを使っていません。
登場、待機、攻撃の3種類のモーションしか使わないし、大げさにする必要もないかなと。
で、Spawn→直後にアニメーション設定とやったのですが、1フレームくらいでしょうか、一瞬だけキャラがTスタンスで立っているのが見えました。
登場モーションはキャラが上から降ってくるようなモーションで、原点で再生すれば問題ないものなのですが、SpawnしたフレームだけTスタンスでっていうのは見臭い。
最終的な対処法は、Spawn時は敵を上空に配置、次のフレームですぐに下に下ろすという形を取りました。
短時間開発のため、AnimBPで作り直す余裕がなかったのですよ…
8. Unpossessすると配置されているカメラにSetViewTargetしていてもカメラが外される
早撃ちSSKの最後に直したバグ。
このゲームはマップ1つでタイトルからゲームまで作成し、ゲーム終了後に再びタイトルに戻るという流れのゲームです。
ゲーム終了時にはSSKはふっとばされてしまうので、プレイヤーポーンであるSSKを一旦削除し、それから再生成→Possessという形で実装しました。
しかし、どうにもうまくいかない。何が原因なのか?
まず1つはSSKを再生成する際にCollision Handling Overrideがdefaultになっていて、多分どこかのコリジョンと干渉して生成されなかったんじゃないかと思われます。
これを、Always Spawn, Ignore Collisionsに変更したら生成されました。
もう1つの問題はカメラ。
SSKシリーズはカメラは基本固定なので、レベル上に普通に配置しています。
レベルBPのBeginPlayイベントでこのカメラにSetViewTargetWithBlendを使ってカメラの変更を行っていたのですが、SSKを削除、もしくはUnpossessするとカメラがSSKと関わりなくてもプレイヤーポーンから外されてしまうようでした。
最終的にはもちろん、SSKをSpawnした後に再びSetViewTarget~を呼び出すようにしました。
とまあ、今回のぷちコンで問題になった部分はこれくらいですね。
今回は有料アセットもけっこう使っているのでプロジェクトの公開はなしです。
申し訳ありません。
もし、この処理どうやってるの?とか質問がありましたらTwitterとかで気軽に声かけてください。