Unityでインディゲーム道!

プログラム、Unity初心者がインディゲーム制作を目指して日々思うことなどを書き綴ります。

ブログ新設しました!本ブログの今後について

心機一転、新しいブログを作りました。その名も・・・

 

 そのまんま過ぎる名前ですが、このくらいが良いなと思いました。何がしたいんだって、Unityでゲーム作りたいんだから、ブログ名もこうすべきっしょ。

 

 というわけで、前回の告知の通り、本ブログに変わるブログを立ち上げました。今後こちらは更新しません。もちろん残しますが、しばらくした後に非公開になったりするかもしれません。

 

また、どこかで、あるいはシン・ブログにて、お会いしましょう!

今までありがとうございました!!

 

ブログの移転を考え中・・・

 ゲーム制作に対するモチベとか取り組み方が変わったり、いよいよ本格的にやっていきたいことを考えて心機一転、ブログの移転を考えています。

 

 基本的には自分向けの記録としてのブログ、という側面が強く、(アクセスが今後、爆発的に増えたとしても)収益化など今後一切やるつもりもないのですが、数年やってきてて自分の書いた記事にそれなりにアクセスがあると。

 それは単純に嬉しく、それに対して一方的に新しいアカウントを作って、ブログ移行機能を使って記事移して、こっちのブログをドーーーンと潰すのも何かもったいなく感じてしまいます。

 

 noteとかもどうなんでしょうねー。はてな村については(最近の騒動も含めて)何だかなぁって感じる派なんだけど、こういうゲーム開発、技術関連のブログははてなが合っているような気もするし、単純に面白い記事を書く人も多い気がする(主観)。

 移転、新設とかのことを考えると、記事書こうと思っても、新しいブログで書いた方がいいんじゃ、とか思っちゃって筆が進まなくなるのは良くないことだと思うので、とっとと決めちゃいたいですね。

 

 という感じで、今回はウダウダ一人言を書く回でした。近々、ちゃんと決断して、シン・ブログを発表出来たらいいな、と思います。

 

久々のUnity探検隊!はなんとも言えないクオリティ!!Battle Toads(バトルトード)、失意の帰還!?

f:id:miur-us:20210603182527j:plain

タイトル画面

 当ブログの名物(!?)企画、Unity探検隊はMade With Unityのゲームを実際にプレイし、そのレビューを書くというものです。

 ブログ投稿自体が、かなり久々で、清々しい内容を書きたかったのですが、残念なことに『バトルトード』は擁護しがたい内容でした…!60点いけば、いい方かな…

 

 およそ6時間ほどで全クリしました。

 

かつてのレア社を代表するアクションゲー

 レア社と言えば、任天堂と組んで生み出した、スーパードンキーコングシリーズが有名です。しかし、その高い技術力をそれ以前に示したのが、バトルトードでした。

 90年代頃、ミュータント・タートルズをはじめとした、動物の擬人化キャラの流行の中で作られた人型カエルを主役にしたNES(海外でのファミコン)作品です。

 

  旧バトルトードは、Youtubeなどでプレイ動画を見ることが出来ますが、今見ても軽快な動きをする、ファミコンの性能を使い切ったアクションゲームであり、レア社が当時のスーパードンキーコングの開発を任せられる存在であったことを感じさせてくれます。

 ファミコンにおいて、高い技術で作られたソフトはいくつかありますが、その中の一つに間違いなく選ばれるでしょう。

 

 上の動画を見れば分かりますが、いろいろな挙動、演出が凝っていて、良くできたゲームですよね。そして、スパドンでお馴染みのデビッド・ワイズ氏による音楽もカッコいい~!!

 

ちゃんと作ればUnityだって軽快なアクション作れるんだ!

 しかし、残念なことに本作の新バトルトードは、かつてのそうした尖った完成度を感じさせるような作品になっていません。

 特に賞賛する技術性もなければ、ゲームデザインとしても微妙で散らかった出来栄えとなっています。90年代のセンスを引きずった、しかし、当時のよく出来たゲームには遠く及ばない退屈なゲーム、と言わざるを得ないです。

 

 Unityと言えば、かつてはクソゲーエンジン呼ばわりされてたこともありました。しかし、今ではFallGuysやHollow Knightなどのヒット作にも恵まれ、きちんと作れば楽しいアクションゲームも作れるのだ、ということを証明しています。

 

 しかし、新バトルトードは残念な事にも、Unityを使いこなしているとは言えず、ゲームとしての体裁は合格点はまぁ超えているにしても、Unityがダメだった時代を思い出させてくれるクオリティなのです。レア社でそれをやっちゃうのは、どうなの!?

 

もはや、ゲーム内ムービーは取扱注意!?

 かつては、ゲームプレイの間にムービーが挟み込まれることが、ゲームの進化を示したこともありました。しかし、今のゲーム、特にアクションゲームにおいては、レスポンスが良く、自由度が高いことが求められます。

 要するにムービー中は自分でキャラを動かせないので、自分の操作を拘束されていることになります。もちろん、カッコいいムービーはプレイヤーのテンションを上げてくれるものですが、諸刃の剣でもある、ということです。

 

 ここ十年くらいで、ムービーの取り扱いが特にうまいなと感じたのは、バットマンアーカム・シリーズです。アメコミキャラであるバットマンのゲームである以上、まずはキャラゲーではあるのでムービーは欠かせません。

 しかし、ムービーが長すぎないように、ダレないように細心の注意が払われており、バットマンの世界への没入感を高めて、しかし、アクションゲームとしてのテンポが損なわれないようにムービーが扱われています。QTEも演出の一つとして、効果的に使われているので、そこを含めて好例の一つと言えます。

 

 まぁアーカムシリーズはワーナーによる、映画スタッフもかかるような大作アクションゲーであるので、そのクオリティを求めるのは酷なのかもしれません。

 

 新バトルトードでは、合間に90年代アメリカンアニメのノリのアニメが挿入されます。これがまた無駄に長いし、だからどうした、という内容ではあるのです。面白いかどうかは個人差があるとしても、無駄に長いのだけは擁護できません。プレイ時間を稼ぐためのもの、と言われてもしょうがない感じです。 

f:id:miur-us:20210603190607j:plain

 で、ムービーの間にしょうもないミニゲームも挟んでくるのでサイアクです。ミニゲームの取り扱いも難しい要素の一つですね。

f:id:miur-us:20210603190843j:plain

 成功したら、ちょっとイイことある!くらいなら良いと思うんですけど、クリア必須なものになってしまうと、苦痛なものになりかねないです。上の写真は左から飛んでくるボール群を右にトスしていく、ってミニゲーなんですが、無駄にムズイ!

 

ゲームとしての統一感とは!

 本作の最大の問題点は、いろんなゲームを詰め込み過ぎて、かつゲームバランス調整が雑なため、一つのゲームとしての統一感がまるでないということです。急に横スクロールになるのは良いとしても、全く違うゲーム性になったり、いきなりシューティングが始まって、それは良いけど無駄に難しかったり、長かったり!

f:id:miur-us:20210603192320j:plain

 ゲームとは本質的には学習し、問題を解決していく遊びです。特にアクションゲーはプレイヤーにどう学習させていくか、ということが最大の課題になるはずです。

 だからこそ、レベルデザイン、バランス調整が必要だし、ゲームを通して行われるプレイヤーの学習に一貫性がないとダメなんではないかと、自分は考えています。

 

いろいろなことが出来るのは楽しい、でも、その幅が広すぎてもダメだろうし、新しい要素が出てくるのが急すぎてもビックリするし、ゲーム性が大幅に変わったら、また一から新しいこと覚えないとダメ、ってなってしまいますよね。

 

f:id:miur-us:20210603195102j:plain

 基本的にはバトルトードはいわゆるファイナルファイトのようなベルトスクロールのゲームなんですが、いろんなタイプのゲームが混ざっています。

f:id:miur-us:20210603192947j:plain

画面の奥方向に走っていって障害物をよけるランゲームや、

f:id:miur-us:20210603193026j:plain

スパドンなどでも、お馴染みの横移動するトロッコゲーム。まぁまだここら辺は自然なゲームですが、どちらもスマホゲー並みか、それ以下の出来なのが…

 

 中盤以降に謎解き要素が強い、横スクロールのプラットフォーマーが始まるんですけど、かなりベーシック内容でこれ序盤に置くべきだし、後半にやらせられても盛り上がりに欠けるんじゃ…と思ったり。

f:id:miur-us:20210603204156j:plain

箱を押して、それでスイッチを押して前に進む!そういうゲーム自体はいいんですけどね…。

f:id:miur-us:20210603204209j:plain

 ゲーム性が違うから、いきなり難しいことやらせるわけにもいかず、ゲーム後半に差し掛かってるのにやや浅い内容にせざるを得ないっていう。

 

f:id:miur-us:20210603195141j:plain

 上から迫りくる壁を逃げるために下に降りていくのも、まぁ定番のゲームではあるんですが…。強制スクロールも扱いが難しい要素の一つかもしれません。

 

褒められる部分は…

 褒めて伸ばす!というのが、当ブログの方針です。批判するもよし!しかし、それ以上に褒める所は褒める!

 

 しかし、今回は難しいかもしれません(泣)音楽もシューティング・ステージはちょっとは良かったけど、総じて普通でしたので。

 ホントにやることがない時にヒマつぶしにはなる、くらいしかないですね。そういう状況で、セールになってる時は買っても良いかもしれません。

 

 なんとかして、ファミコン版バトルトードをやりたいな!という気持ちにはさせてくれました。(褒めてるのだろうか…)

 

まとめ!

 というわけで、一年ぶりのブログ更新がこうしたネガティブなものになってしまったのが残念ですが、Unity界を盛り上げたい!Unity製の良いゲームを発掘、発信したい!というテーマの下でやっている以上、何様!と言われようと悪いものは悪いと言っていかなければいけないんじゃないかと。

 ゲーム批評の重要性については、いろいろ最近思うことがあったで、後日にそれについての記事を書こうと思っています。褒めるものは褒める!貶すものは節度を持って貶す!というスタイルで行きます!!

 

 というわけで、新バトルトードはおススメがすることが…難しいです!

ごめんなさい!!

 

聖剣伝説3の体験版をやっての感想 [Switch版]

f:id:miur-us:20200322195655j:plain

画像はMy Nintendo Storeの商品ページから引用

 ごくいくつかの不満点を除き、かなりの良リメイクだと思いました。2のリメイクはかなり評判が悪く心配でしたが、Switch版を買いたいと思います。

では、少し気になった点から・・・

 

気になった点とか改善案とか

キャラ選択画面でCV(声優名)を出す?

 一番これはなくね?と強く思ったのが最初のキャラ選択画面でキャラの声優名が表示されることです。声優陣の方々の演技はどれも良いです。脇役もいい感じです。だからこそ、名前を出して世界への没頭感を削ぐようなことはやめてほしかったし、今からでも間に合いますよ、スクウェアさん!

カメラとプレイヤーの間のオブジェクトの透過

 3Dゲーム化ということでカメラを動かせますが、プレイヤーとカメラの間に壁ではないオブジェクトが入り込んだ時見辛いです(特にカメラとオブジェクトが近い時)。例えば木の枝だったり、柵とかの障害物ですね。大体の最近のゲームであれば、オブジェクトを半透明にしてプレイヤーを見えるようにする、というようなことをやっているはずです。

リングコマンド選択中の画面

 聖剣伝説と言えばリングコマンド!左十字キーの上と下はそれぞれ特技とアイテムのリングコマンドなのですが、これの発動中はゲーム内の時間が止まります。原作だと2と3もリングコマンド発動中は画面が暗くなるのですが、このリメイク版だと単純に画面が止まるだけなので味気ないですし、リングコマンドに意識が行きにくくなっているかもしれません。 

戦闘カメラは俯瞰にした方がよかったのでは?

 聖剣伝説は仲間と共に旅をして一緒に戦うことが醍醐味ですが、戦場全体の状況が分かりにくいですね。2と違って3はシンボルエンカウント方式のアクションRPG、という感じになっているのですが、原作のように上から俯瞰するカメラ位置に切り替わるのが良かったのかもしれません
 敵と一体一の状況ならともかく、多数対三人だと全体の状況が分かりにくいとダメだと思うんですよね。あるいはTPS視点と俯瞰視点を切り替えられるように出来れば良かったのかもしれません。

街中で剣振るヤツ

 これもまた世界観が削がれるし、コミカルよりのRPGとは言え、街中で剣を振り回すのはなーと。

画面へのポストエフェクト

 アクションRPGなので見やすさ優先だと思いますが、例えばオクトパストラベラーのように、もう少し画面にポストエフェクトを効かせても良かったのではないかとは感じました。ファンタジー作品ですし。


 これらの以外はリメイク作品としては良い部分が多く、発売がかなり楽しみな出来です。というか、体験版をもっと早めに出して、プレイヤーかのらフィードバックを貰うべきだったのでは?とすら思います。

 

良かった点とあの頃のスクウェア

素晴らしい音楽

 やっぱ音楽がいいですね。オリジナルの音源も収録されていますが、本作のグラフィックとは合わないと思うので素直にリメイク版の音源がいいと思います。デュランでやってみたのですが、船出のオープニングシーンは少し鳥肌が立ってしまいました。

キャラのモデリング

 メインキャラのはもちろん、敵キャラ達も原作再現度も高い、かなりいい感じになっていると思います。衣装もある程度変えられるみたいだし、クラスも増えてるみたいなのでかなり楽しみです!

ゲーム性とテンポ感

 25年も前のゲームなので、ゲーム性はそこまで期待はしてなかったのですが、いい意味で軽い感じで楽しめるようになっていると思います。ダクソのように崖から落ちたりもしません(笑)

 アクション性が高くなってはいますが、そこまで難しくはなっていないはずです。ジャンプできて空中の敵に攻撃できるのはいいですね、ただジャンプが回避行動として強すぎる疑惑がありますが。ノーマルとハードでやってみましたが、経験者はハードがいいのかなと思います。

 

 で、やっぱ昔のゲームなのでテンポがいいですね。お話もポンポン進みますし発売されたら疲れきるまでずっとやってしまうと思います。

育成要素

 原作の記憶もかなり薄れてますが、レベルアップするとポイントが割り振れるシステムでした。リメイクだとポイントを各ステータスに割り振ることでスキルやアビリティが覚えられるシステムになっています。ここにクラスチェンジが絡んでくるので、いわばFF5のような感じになるのかと考えると、かなり楽しいことになりそうです!

これを発展させた新しいゲームを作ってほしい

 あくまでリメイク作品という但し書きが付くし、思い出補正もあるのかもしれませんが、現代でも十分魅力のあるゲームとしてきちんと作り込まれているのかな、と思いました。体験版は体験版なので、製品版どうなるか、という感じですが。

 

 やっぱ、このシンプルさとか分かりやすさが当時のスクウェアの魅力だったと思うし、現代でも求められていることだと思うんですよね。

 別に今のスクエニじゃなくてもいいから、今回の聖剣伝説3のような路線、世界観、ゲーム性を引き継いで、現代のゲームとしてさらに昇華させた作品を作って欲しいなぁ。あるいは、このブログでそういう方向性の作品を作っていくべきか・・・?

 

まとめ

 というわけで、聖剣伝説3の体験版をやってみた感想を書きました。カニのボスを倒してちょっと進んだ所までなので、遅くとも二時間はかからない程度なので興味のある方は触ってみるのがいいと思います。

  

DOTSで玉転がしゲームを作ってみた!後編 [ Unity_2019.3x, Entities_0.6 ]

f:id:miur-us:20200320021954j:plain

 前回は前置きだけで終わってしまったので、今回はいよいよDOTSで制作した玉転がしゲームの中身について書いていきます。8000文字を超える大作です!

 

 本ブログのチャンネルを設立し、テストプレイ動画をアップしました。音もない状態ですがひとまず。

 

 DOTS及び、ECSの考え方などを自分の勉強した範囲で確認していきつつ、実際にどのようなコードを書いたかについてまとめていきます。

 Entitiesパッケージ自体は現在0.8まで出ていて、正式版までそう遠くないのかなーという感じです。しかし、今回使用したDOTS向けの物理演算パッケージであるUnity.Physicsはまだ0.3であり、対応するのがEntities 0.6なのでEntities 0.8は使いません。試用版における現状の安定版がEntities 0.6 & Unity.Physics 0.3ということになるでしょうか。

 

 そして、前回の繰り返しになりますが、DOTSはまだまだ開発中であり、各パッケージの多くは試験段階のものです。今後の開発状況により、その中身は大きく変わり得りますし、本記事のコードも将来的に通らなくなる可能性があります。その点だけご了承していただくようお願いします。

 今回の玉転がしゲーム制作にあたり、DOTSに関しては前回も紹介したUnity公式動画のPong及び、海外のUnity開発系YoutuberであるCode Monkeyさんの動画などを参考にしてます。CodeMonkeyさんはUnity Japanの方でもオススメされてた方のようなのでぜひ!

 当然ですが、これらの動画の内容も今後古くなってしまう可能性があります。

 

ECSコンポーネント

 まず従来のUnityにおけるコンポーネントとはGame Objectにアタッチする部品、モジュールであり、これにより様々な機能をゲームオブジェクトに持たせることが出来ました。これをGame Object コンポーネント(以下、GOコンポーネント)とします。

f:id:miur-us:20200320024014p:plain

 これに対し、ECSにおけるコンポーネントというと、基本的にはデータのみ、つまり特定のタイプの変数だけをもつ単純な構造体(struct)となり、これをここではECSコンポーネントとします。

f:id:miur-us:20200319065549p:plain

 MonoBehaviourは外してしまい、IComponentDataというインターフェイスを継承させたシンプルなstruct(構造体)です。[GenerateAuthoringComponent]というattributeをC#スクリプトに付け加えることで、Unityエディター上でGOコンポーネントと同じようなコンポーネントとして扱えるようになり、初期値設定などを行えるようになります。

f:id:miur-us:20200320024154p:plain

 後はConvertToEntityというコンポーネントAdd Componentからゲームオブジェクトにアタッチすれば、ゲーム起動時にECSが自動でEntityに変換してくれます。ね?簡単でしょう?(Sub Sceneを使ったEntity変換もあるのですが今回は省きます)

 

やってることは3つだけ!

 で、この単純なゲームを作るためにやったことは基本的に3つだけで、ECSコンポーネントを書き、ゲーム内の処理をするJobComponentSystemを書き、そのECSコンポーネントをゲームオブジェクトにくっ付けて値を設定する、になります。

 

 もちろんステージ設計やボールのマテリアル、キューブを取った時のパーティクルエフェクト作成等の細かい作業はありましたが、ECS関連の作業はこれだけです。このゲームで作ったスクリプトは全部で10枚で、内訳はコンポーネントデータが4枚、システム系は5枚、後はいわゆるゲームマネージャー・スクリプトの1枚となります。

[Data]

BallinputData //コントロールのためのキーを指定する

PlayerBallData //ボールを動かすためのデータをまとめる

StarCubeTag //そのEntityがスターキューブであることを示す

ToPlayerDistanceData //プレイヤーとの距離を格納する

 

[System]

BallControllSystem //プレイヤーの入力をPlayerBallDataに入力する

BallMovingSystem //ボールを動かす

StarCubeRotateSystem //スターキューブを回転させる

StarCubeCollectSystem //スターキューブをプレイヤーがゲットする処理

FollowPlayerPosSystem //プレイヤーの位置をゲームマネージャに伝える

ToPlayerDistSystem //各スターキューブとプレイヤーの位置の計算

 

 下二枚の画像はゲーム全体を管理するGameManagerスクリプト。参考のために載せますが、今回の本質ではないので読まなくていいヤツです。

f:id:miur-us:20200319071117p:plain

f:id:miur-us:20200319071953p:plain

  今回はカメラの処理や、スコアの表示などの雑多な機能はゲームマネージャースクリプト内で行っています。シングルトン・クラスとしていろんな所で活躍。

 例えばSetPlayerPosはEntity化されたプレイヤーボールの位置をこのクラスに教えるメソッドであり、そこを元にLateUpDate内でカメラを動かす処理が行われます。ですが細かい説明は省き、DOTS, ECSのコードについて見ていきます。

 

必要なデータと機能

f:id:miur-us:20200320030800p:plain

 このゲームに必要なデータは、まずプレイヤーキャラを動かすためのコントロールの設定、スピードや集めるキューブの回転スピード、プレイヤーとの距離です。必要な処理は、プレイヤー入力の受付、そしてそれに応じて玉を動かすのと、キューブを回転させる、プレイヤーとキューブの距離を計算、そして十分近づいたらキューブを消して、パーティクルを出す、となります。

 まずはそうした必要なデータ、およびそのまとまりをECSコンポーネントとして定義して、必要なゲームオブジェクトに取り付けていく、ということです。

 

 データ指向プログラミングといっても、必要なデータを考え、それをどういう風にまとめるか、それらをどういう処理するか、コンポーネントやシステムの名前はどうするか、というプログラミングの基本は変わらないはずです。

f:id:miur-us:20200320024553p:plain

 例えば上画像のJobComponentSystemスクリプトはプレイヤーのEntityとToPlayerDistanceDataコンポーネントを持つEntityの距離を計算するシステムなので、ToPlayerDist(ance)Systemとしています。システムが一つの関数であるかのように捉えるのがいいのかもしれません。

 

Entities.ForEachというメソッド

 いろいろ細かいことは多いのですが、現時点で最も簡単にDOTSの恩恵を受けられる処理の定義の方法が、JobComponentSystemのOnUpdate関数内部でEntities.ForEachというメソッドを使う方法です。

f:id:miur-us:20200320024940p:plain

獲得するキューブを回転させるシステム

 ForEachは名前の通り、各Entityをそれぞれ処理をする、というものですが、実際やっていることは、コンポーネントから処理したいEntityを絞り込んでの一括処理です。

 そもそもEntityのコンポーネント構成のことをArchetypeと呼び、それに基づいたEntityの絞り込みをEntityQueryと呼びますが、そこらへんは細かい内容なので省きます。とにかく今回のような単純なプロジェクトであれば、とりあえずJobComponentSystemを書いて、そのEntities.ForEach内で処理すれば十分だということです。

Entities.ForEach( ( //パラメータ )={ //処理 } ).Run();

 

f:id:miur-us:20200320030031p:plain

 プレイヤーの動く方向やスピードを格納するECSコンポーネント。このように単純な変数のまとまりとしてECSコンポーネントを書き、オーサライズする!

 ちなみに環境設定で構造体のフォントカラーを青緑にしてclassと見分けがつきやすいようにしています。

f:id:miur-us:20200320025605p:plain

 このBallControllSystemではプレイヤーからの入力に基づいて、移動方向を計算し、PlayerBallDataのmoveDirectionに格納します。mathは従来のmathfではなくUnity.Mathematicsパッケージによる数学ライブラリで、normalizesafeを使ってfloat3を正規化しています。

 

f:id:miur-us:20200320025521p:plain

 このように自分で作成したECSコンポーネントデータもパラメータとして、ForeEach内で使用することが出来、refキーワードを付ければデータを操作することもできます。Entities.ForEach内部にはいろいろ制限も多いですが、単純なことは圧倒的な処理速度で実行でき感動します。

 

ECSでのRigidBody

f:id:miur-us:20200320030225p:plain

 Unityでの物理演算と言えば、RigidBodyコンポーネントですが、DOTSではPhysics BodyPhysics Shapeコンポーネントです。Physics BodyはいわゆるRigidBodyに代わるもので、Physics ShapeはColliderなどに該当します。

Add Component>DOTS>Physicsから選択可能です。

 もし物理演算によって動かす必要が無い場合は、Physics Shapeだけでいいようです。なので、ステージの壁や床にはPhysics Shapeを付けます。(一応、変換時に自動で従来のColliderをPhysics Colliderに変換してくれます)

 

 Unity.Physicsは決定論的な物理演算ということで、観察してると正直けっこう人工的な動きではありますが、従来のUnityの物理演算からするとかなり滑らかな動作で驚きます。(より高度な物理演算用にHavokのUnity版も開発中です)

 

物理でボールを動かす

f:id:miur-us:20200320025521p:plain

  前述のPhysics Body とPhysics ShapeはECSワールド内ではいくつかのコンポーネントに分解されます。その中で、物理演算による動く方向はPhysics Velocityというコンポーネントで指定できます。

 Physics VelocityのLinearという変数にfloat3を加算すれば、物理ボールを物理的に動かすことが出来ます。入力するfloat3の値は動く方向×スピード、です!

PhysicsVelocity.Linear = moveDirection * moveSpeed;

 

プレイヤーコントロール

f:id:miur-us:20200320024418p:plain

 キーボードをコントローラとします。PlayerInputDataでは、入力に使うキーボードキーを指定します。これは参考にしたUnity公式によるPongの動画の影響で今回のゲームでは特に必要が無いのですが、2人対戦の場合も考えて残します。

 いわゆるFPSなどでも使用するWASDキーを使います。

f:id:miur-us:20200320025605p:plain

 ここで指定したキーをBallControlSystemでチェックして、押されていたら1、-1を変数に足すようにします。こうすることで反対方向のキーを同時押ししたら止まるようにします。そして、PlayerMoveDataにプレイヤーの進む方向を入力します。

f:id:miur-us:20200320030007p:plain

 PlayerMovementSystemではPlayerMoveDataに入力された進行方向及びスピードデータを取得して、実際に動かす処理をします。前述のとおり、Physics VelocityのLinearパラメータに入力するだけです。

 で、遊びでジャンプする機能も付けてます。スペースキーをチェックして、かつLinear.y(上下の動き)が絶対値で0.2以下か?つまり空中にいないかを簡単に確認して、Linear.yに値を加える、ということでジャンプさせています。(坂道だとたぶんジャンプできなくなる実装)

  

Entityを回す

 ECSでは従来のTransformに代わり、position, ratation, scaleを含む4x4行列であるLocalToWorldというECSコンポーネントが加えられ、TranslationRotationというコンポーネントも付随でEntityに付与されます。

f:id:miur-us:20200320031240p:plain

 Rotationはそのまま『回転』ですが、Translationは要するにTransformのPositionなので動かしたいときはこれを操作すればいいです。というわけでキューブを回転させたいのでRotationを使います。

 RotationはUnity.Transforms.quaternionなのですが、従来のQuaternionとは別です。今回quaternionを使うと上手くいかなかったので、従来のQuaternionを掛けています。

quaternionはQuaternionと区別するためにUnity.Transforms.quaternionになるので注意が必要、というか名前付けどうにかならんかったのかと。(using文で宣言する方法あり)

 

f:id:miur-us:20200320031549p:plain

 今回はスターキューブだけ回転すればいいので、上のような空のECSコンポーネントを作成し、タグとして使います。StarCubeRotateSystemではWithAll<>メソッドでこのタグを目印に処理をするEntityを絞り込んでいます。

 オブジェクトを回すのは決して安い処理ではないはずですが、この簡単なシステムにより高FPSでグルグル回ってくれます。

 

距離を測り、当たりを確認する。

f:id:miur-us:20200320032120p:plain

プレイヤーとの距離を格納

 ColliderもUnity.Physicsの領域で、Colliderを使った接触判定も考えたのですが、難しそうだったので今回はもっと単純な方法を採用しました。毎フレーム、各キューブとプレイヤーの距離を計算して、一定の距離以下になったら触ったと判定して、キューブを取得したことにする、という方法です。

 

 ToPlayerDistDataというECSコンポーネントを作り(上画像)、キューブにアタッチします。ここにプレイヤーとの距離を格納するわけです。

f:id:miur-us:20200320024553p:plain

 ToPlayerDistanceSystemでは二つのEntities.ForEachを使い、プレイヤーの位置を求め、そして、各キューブとの位置を計算し、ToPlayerDistDataに入力する、という処理をシステムです。

 

キューブをゲット!Entities.Foreachの制約とは?

 ということで距離を毎フレーム計算しているので、あとは一定の距離以下に近づいたら、キューブEntityを消去し、スコアを加算し、視覚エフェクトを出す、というシステムが必要になります。

 

f:id:miur-us:20200320032327p:plain

 いくつかあるForeach内部での大きな制約の一つとしてclassのstaticメソッドが使えないことです。WithoutBurstメソッドを使うことでこの問題を回避できます。

 まだ詳しくは理解していないですが、Burstコンパイラーによるコンパイルをしないことでそうしたstaticメソッド実行可能に出来る、ということのようです。当然ですが、BurstCompileできないということはパフォーマンスが落ちるということであり、大規模な処理では、できる限り使わないのがいいのだろうと思います。

f:id:miur-us:20200320040938p:plain

 FollowPlayerPosSystemはゲームマネージャ・スクリプトインスタンスを通じて、カメラにプレイヤーの位置を伝えるシステムです。このように従来のゲームオブジェクトとEntitiyとの連携をどう処理するかが課題になると思います。

 

 ECSにおいて、Entityを作ったり、そのEntityにECSコンポーネントを加えたりするのはEntity Managerの仕事なのですが、なんとEntities.ForEach内部ではEntitiesに対して、その構造を変化させたり、ECSコンポーネントを着脱するような処理を行うことが出来ません。

そこでEntityCommandBufferの出番になります。

EntityCommandBuffer ecb =

          new EntityCommandBuffer(Unity.Collections.Allocator.TempJob);

 

EntityCommandBufferとは?

公式ドキュメントの説明文を引用すると、

A thread-safe command buffer that can buffer commands that affect entities and components for later playback.

『Entitiesやコンポーネントに影響を与えるような命令を後で再生できるようにバッファすることのできる、スレッドセーフなコマンド・バッファ』

 バッファとは溜め池、ダムのようなもので、ここでの理解は『コンピュータへの命令を一時的に記録する機械』というものでいいと思います。

 

 つまり、Entities.ForeEach内部では、Entityを消去したりコンポーネントを付けたり外したりするような命令は直接実行できないので、EntityCommandBufferに記録しておいて、Entities.ForEachが終わった後、Entity Managerに対して記録された命令を再生することで事後的に処理を実行させる、というのがEntityCommandBufferの役割となります。

 

 つまりStarCubeCollectSystemにおいて、Entityを消去するというのは、Entitiesの構造を変えるような処理なので、EntityCommandBufferにDestroyメソッドを記録させ、ForEachの外でそれをEntityManagerに伝えて処理を実行してもらう、という流れになります。

 

Entitiy Debuggerとは

f:id:miur-us:20200320033057p:plain

 EntityToConvertコンポーネントによりEntityに変換されるゲームオブジェクトは、上画像のようにプレイモード中はヒエラルキーウィンドウ内に表示されません。ECS worldの中にどんなEntity達がいるのか、何が起こっているかを確認するのにEntity Debuggerは大切な存在です。

f:id:miur-us:20200320040549j:plain

 EntityDebuggerはWindow>Analysisから選択でき、上画像ではエディター下部にドッキングしています。

 

f:id:miur-us:20200320033019p:plain

 見方としては、左がシステムでここでそのシーンでどのシステムがあるか、どのくらいの負荷で処理されているか、あるいは停止しているかを確認できます。真ん中はEntities欄で全てのEntityであったり、システムに関わるEntityを検索することも可能です。一番左はコンポーネントで、どういうECSコンポーネント構成になっているかを確認できます。

f:id:miur-us:20200320040643j:plain

 このようにシステムを選択し、コンポーネントをクリックすると該当するEntityのみが表示されます。

 

  そして、ここでEntityを選択するとInspectorウィンドウにそのEntityの情報が表示されます。もちろんリアルタイムで値も動くのでどのように処理されているかもモニターでき、下画像上部のStarCubeDistanceDataのdistance(float)項目でリアルタイムで距離が計算されている様を確認することが出来ます。

 自分もまだまだ使いこなせていないですが、かなり簡単で便利なデバッグツールなんじゃないかなと思います。

f:id:miur-us:20200320033742p:plain

 

まとめ!

 ということで、DOTS学習のために玉転がしゲームを制作した中身について書いてみました。DOTS関連については、このゲームを作ったり、この記事を書いている間にもどんどん開発が進んでおり、実際Verごとにドキュメントの内容も大きく変わったりもします。

 なので、いろいろ調べつつ学ぶには少し時期尚早な感じもしますが、DOTSの可能性を肌で感じてしまうと、どうしてもその考え方や使い方に早く慣れたい!という気持ちが強いので、様子を見ながら学習を進めていきたいと思います。 

 

DOTSで玉転がしゲームを作ってみた!前編 [ Unity_2019.3x, Entities_0.6 ]

 Unityの新たな可能性の一端を示すUnity 2019.3ですが、その中でDOTSの開発は大きく進み、プレビュー版ではありますが自分なりにいろいろ試しています。まだ分からないことが多いですが、かなり面白いです!

 

 『とにかく簡単なモノを作ってみる』というのはプログラミング学習における定石であるので、とりあえずUnityのチュートリアルとしても代表的な玉転がしゲーム"Roll a Ball"をDOTSで作ってみました。

  少し前置きが長くなってしまったので、前半後半に分けています。前半では、今回初めてDOTSと向き合い、実際に使ってみてどう思ったのかが中心の内容です。 

※[更新]後半記事をアップしました!

 

f:id:miur-us:20200304233443j:plain

 

注意点!

 DOTSに関わるパッケージやそこに含まれるライブラリの多くは、まだまだ開発途中のプレビュー版です。プレビュー版の不具合による被害は保証されません!そしてAPIなども今後変わっていく可能性があり、記事内のコードも動かなくなるかもしれないので、あくまで参考程度に見て頂ければ幸いです。また単純な間違い、理解不足もあるかもしれません。

 

DOTSの可能性がスゴイ!っぽい

 近年のUnityはいろいろな変化や進化がありますが、その中でも特に目玉なのがDOTSです。

DOTSとはData-Oriented Technology Stackの頭文字を取ったもので、

ECS(Entity Component System)

JobSystem

Burst (Burst Compiler)

 という三つの技術をまとめたものですが、以前のDOTSを利用するためコードというと、かなり難解で複雑そうなC#コードを書かなければならず、これはちょっと自分には無理だなーと覗いてひとまず離れてしまっていました。しかし最近の改定でそれなりに分かりやすいコードでDOTSを利用できるようになったので触ってみた、というのが今回の経緯です。なにより、DOTSへの興味というのはUnityのパフォーマンス改善への期待から、かなり強くありました。

 少しずつですが、上のような解説動画やデモプロジェクトなども出て来始めていたので、そのおかげもあります。

 

 現在、恥ずかしくないクオリティを持ち、評価も受けているUnity製のゲームがどんどん出てきています。しかし、この令和の時代になんとも言えない動作感を出すUnityゲームがあるのも事実であり、自分だけでなくUnityのパフォーマンス向上というのは多くの開発者を悩ませていたテーマです。(もちろん開発者がきちんと対応すれば、従来のUnityでもそれなりのパフォーマンスが出ていたのですが)

 

 C#でコーディングする以上、パフォーマンスが犠牲になることは仕方ない・・・しかし、Unityは意外なパラダイムシフトでこの問題の解決を図ります。それがこのDOTSであり、データ指向という考え方でした。

 今回の"Roll a ball"ゲーム作成のためにDOTSに初めて取り組んだ感想としては、少し苦労もしたけどDOTSの考え方が単純に面白いと思いました。そして結果としてのパフォーマンス向上が明らかに見て取れたので、この新しい技術を学ぶ決意ができた!という感じです。

 

DOTSへの不安とデータ指向の可能性

 もちろん開発途中であり、まだなんとも言えない部分が多い技術であるのは確かです。しかし、今回のようなシンプルなゲームはまだいいとして、もう少し規模の大きいゲームやAAA規模のゲームでこのDOTSは適用できるだろうか?という不安、疑問を抱きました。

 

 データ指向とは言わばアンチ・オブジェクト指向なのではないかと思います。オブジェクト、つまりプログラム内部のモノや存在を中心に捉えるのではなく、データを中心にプログラミングを考える、という考えです。

 ECSはゲームワールド及びそこにあるオブジェクトをどう表現し、処理するかのためのシステムで、Entityはいわゆる従来のGameObjectに代わるモノを表す単位です。しかし、Entityはあくまでデータテーブルの行番号を表す程度のものでしかなく、システムとしてはデータ主体で動きます。

 

  というか、そもそもコンピュータが扱うものは全てでデータであり、そのデータを抽象的なオブジェクトとして定義し、問題解決を図るオブジェクト指向はむしろ人間本位な考え方だったはずです。巨大なプログラムをクラス単位で分割する、というのは妥当な方法論であるはずですが、その分割や抽象化、クラス間の連携が難しいために批判も多い手法なのかもしれません。なので、たぶんデータ指向とはもっと単純に物事を考えよう!という方法論なのだと思います。

 

 今回、DOTSプログラミングでの作業工程は大きく分けて二つで、『関連する変数をまとめたComponent Data』を作り、『Component Dataからデータを入力し、処理したデータを出力するジョブコンポーネントシステム』を作るというものです。

  

発想の転換

 そう考えると、むしろオブジェクト指向におけるどうデータをまとめるべきか?(カプセル化すべきか?)の分割の規模は緩くなっていると考えられます。

f:id:miur-us:20200304233708p:plain

オブジェクト指向はデータの集まりを人物かのように抽象化する

 オブジェクト指向というのは、クラスという単位でプログラムを分割して人間がとらえやすいように抽象化し、実行時にはそのクラスから生まれたインスタンスが主体性をもっているかのように振舞い、各々処理していく、という考え方です。

 

 データ指向はそうではなくて、必要なデータ群を単純な構造体(struct)として定義して、『振舞い』は持たせない。そうして出来たComponent Dataを組み合わせて、Enitityを表現するが、Entityはあくまで個を区別する目印程度のものでしかなく、関数はデータから切り離し、ジョブシステムをひとつの関数として定義していく、というものです。Entityは振舞わず、システムもEntity自体はほとんど意識せず、データを主眼に動いているような構造になっています。

 

 慣れさえしてしまえば、オブジェクト指向よりも簡単になる部分は多いように感じました。必要な変数とその名前を考え、いかに必然性のあるまとまりにするか。また、やりたいことを実現するにはどんな処理を理解し、その問題を解決する関数の名前を考える、というプログラミングに必要な作業というのは変わらずに、その視点を変えた考え方にものすごく興味が湧いています。

 

次回へ続く 

 前述したように、大規模なゲームでこうした細分化していく考えは通用するのか、多くのスクリプトをちゃんと管理できるのか?という不安を実際の作業をしながら感じたのは事実ですが、触っているうちに「これ相当革新的じゃね?」と思いましたし、自分はあくまでインディ個人開発者だし、とにかく面白そうだからやってみるわーという態度に臨んでいこうと決意しました。

 

 というわけで、後半では実際にDOTSで作ったRoll a Ballの中身を見ていきたいと思います。(近日公開)

 

2020年を迎え、これからのUnityについて考える![Unity 2019.3]

 2020年を迎えて、Unityのこれからの展望、新機能などについてまとめていきます。と、この記事を書いている時に、待ちに待ったUnity 2019.3の正式版が発表となったのでいいタイミングでした。

(※日本語版は近日公開予定) 

 

 Unityの今後については非常に明るいもので、2019.3で実装されたものや今後予定されている新機能はマジで期待の高いものばかりです。なので、Unity触りたいけどまだ触れてない、これから使ってみたい!という方はボチボチ準備を始める時期かもしれません。後述しますが、ここ数年のUnityは刷新の時期に入っていて、特に2020年は大きな変化がある年になるはずなので、いつやるか?今でしょ!です。

 

 今回の記事では、Unity2019.3以降、あるいはUnity 2020以降についての注目すべきところを書いていきます。

 

Unity 2019.3について

 もう既に2020年になっていますが、Unityはまだ2019.3が出たばかりという段階で、多少の開発の遅れがあるかもしれません。詳しくは知りませんが、機能が増えたり、一新されるということでいろいろ困難があったようです。(2019.4が長期サポート<LTS>となり今春公開予定)

 

 2019.3の大きな目玉がUnityエディターの改定です。見にくさ、使いにくさに定評のあったUnityエディターですが、いよいよ手が加えられます。

f:id:miur-us:20200130135405j:plain

 分かりやすいところで言えば、上画像のようなアイコンも刷新され、より作業効率が改善されるような抜本的なもの。

 

 他にはVFX Graphが正規版となり、Shader Graphとの連携機能も追加されます。VFX Graphというのは要はGPUパーティクルであり、従来のシュリケンとは違い、GPUの処理能力を利用し、より大量のパーティクルを描写することで、更なる視覚効果を得ようというものです。

 

 LWRP, HDRPを含むSRPといったレンダリングをカスタマイズできる機能は近年のUnityの中でも大きなトピックですが、Shader graphを含め、2D機能が強化されたことにより、よりグラフィックが強化された2Dゲームの登場が期待されます。Unityの2Dゲーとしては質、内容共に高いホロウナイトなどがありますが、2Dゲームエンジンとしての更なる進化に期待です。

 

Universal Render Pipelineについて

f:id:miur-us:20200130133429j:plain

 Light Weight Render Pipelineとされていたものが、より適切な名前に、ということでユニバーサル・レンダー・パイプラインと改称されます。中身はLWRPの延長線上にあるものですが、より改良がくわえられた形で2019.3で導入となりました。

 最終的な画面に効果を加えるポスト・プロセッシング機能が改良された上でURPに統合され、従来のレンダリングよりも負荷が少なくなるとのことです!

 こちらの動画は英語のみで30分を超える内容ですが、URPが詳しく解説されており、デモを見るとUnityでこんなグラできるんだ!という驚きがあります。

 

 フォトリアル向けのHDRPも2019.3から正式導入なのですが、自分を含めたインディーゲーム制作者にとっては、URPでも十分すぎる美麗なグラが出せるようなので、とりあえずURPをうまく使えるよう学習を進めていきたいところです。

 

Unity 2020以降について

 まだ試験段階の機能がいろいろと多いUnityですが、特にUnityの問題点であったパフォーマンスを改善するであろうDOTSは待ち望まれる進化です。

Data Oriented Technology Stack

の頭文字をとってのDOTSドッツ)となります。

 しかし、データ指向とはなんでしょうか?今現在の自分のざっくりとした理解としては、いわゆるオブジェクト指向は人間の認識においては都合がいいが、コンピュータにとっては扱いにくいので、コンピュータにとって都合が良い、より簡素なデータの集まりとしてゲーム内のオブジェクトを定義して、効率的に処理を行えるようにしよう、という考え方のようです。(違ってたらすいません!)

 

 DOTSはいくつかの技術を集積したものです。Entity Component System、JobSystem、Burstといった複数の新技術を使い、より高いパフォーマンスを出そうというシステムになります。

 

 Unityでは『存在』の単位としてGame Objectが用意されていますが、DOTSにおいては、Entity(エンティティ)が準備されています。DOTSにおいてはオブジェクト達はEntityとコンポートネント・データが織りなす、シンプルなデータテーブルとして表現され、コンピュータがよりアクセスしやすく処理しやすいデータ構造になる!という感じです。

 従来のゲームオブジェクトだとオブジェクト単位でアクセスしていく必要があったのが、DOTSではEntityのデータはより単純なデータ列として扱われるので、CPUにおけるキャッシングを活用できるようになります。つまり、まとめてアクセスし、まとめて処理することが出来るようなるとのことです。

 ここら辺の理解については、CPUやメモリ回りの知識が必要になるので勉強中ですが、正式導入が楽しみでなりません。2019.3では、DOTSについてより分かりやすいサンプルプロジェクトも公開されるようです。

 

 また実験的な機能であった、Incremental Garbage Collectionも2019.3で正式機能になったようで、これもまたUnityで顕著であった、一瞬フリーズする現象を打開するものでこれも喜ばしい改善になります。(GCを一回のフレームでなく、複数に渡って少しずつ処理することで瞬間的な負荷を減らす機能)

 

 Unityはスクリプト言語としてC#を採用していますが、わかりやすい言語である代わりにC++などと比べると動作が重くなってしまう問題点がありました。DOTSを活用すれば、C#で書かれたコードでも高いパフォーマンスが出せるようになるみたいなので、ぜひとも押さえておきたい新機能ですね!読み書きし易く、しかも速いなんて最高!!

 

Unityの未来

 主な変更点、新機能の中でも自分が気になった所だけ書いたので、まだまだ他にも大きなモノがたくさんありますし、他のトピックについては随時このブログで触れていきたいと思います。

 

 繰り返しになりますが、Unityの未来は非常に明るいものだと確信しています。現状、エンジンとしては完成度の高いUnrealの方が、より高度なゲームが作るのに向いていることは間違いないのですが、それは当然Unrealが完成しきったエンジンであるからで、Unityはまだまだ発展途上の存在です。

 更に現実問題としては、Unityが予定している機能を実装しきって新世代のエンジンとなるのはまだまだ時間が掛かるというのが、正直な所でもあります。

 

 しかし、近年では質の高いUnity製のゲームやアプリが出回りつつありますし、その将来性を信じて、日々いちユーザーとして準備を進めていきたい!というところで、書き終えたので早速2019.3を触ってきます!!