Created: 2025/04/06
大学のオリエンテーションを終えて2年生になったところでスペースロボクラ(仮)の現在の進捗について再び記事にまとめようと思います。長い間更新が止まっていたせいで良くも悪くも多くのアップデートがありました。
まず、前回の記事の「今後の課題」の章で説明していたDataBaseスクリプトの作成やUIの整備については予定していた機能の実装はあらかた終わっています。下の画像が現在のスペースロボクラ(仮)のEdit画面です。
どこが改善したか具体的に説明します。まずプログラム的にはブロックのプレハブデータをDataBaseスクリプト内で一括管理しそのデータを他のスクリプトが受け取って利用する形に変更しました。その仕組みを元にブロックの選択ボタンがブロックのデータをプログラムが読み込んで自動で配置されるようにしています。またブロックの量が一定量を超えるとブロックのボタンをスライドさせる横スライドを表示しスライド移動で選択画面からはみ出したブロックの選択ボタンもちゃんと選択できるようにしています。
もちろんこれだけでは終わりません。
今回新しい追加要素としてロボットの関節を司るJoint系パーツと弾を発射するGunパーツを実装しました。前述の画像の中央にデカデカと写っているロボットは実際にそれらの追加パーツを用いて制作したロボットです。いままでのスペースロボクラ(仮)ではロボクラとは名ばかりの戦闘機や宇宙船を作るのが精一杯でしたが、今回から実際に手足が動き、おまけに銃弾まで発射できるロボットを作れるようになったのです。
現時点で実装されているまともに動くJointパーツはHandsJointとLegsJointの二つになります。
HandsJointは接続されたパーツを「マウスが左クリックされているときマウスカーソルから発射されたRayの着弾地点に回転させる」処理を行います。つまり左クリックするとカーソルが示している場所に自動で照準を合わせてくれます。あとはパーツにGunパーツを取り付ければそれだけでカーソルの示す場所に銃弾を発射してくれる武器システムが完成するわけです。このパーツの利用方法はそれだけにとどまらず、例えばこのサンプルロボットでは首の可動にもHandsJointを利用することでカーソルの方向に腕だけではな頭部も指向するようになっており、ロボットの動きを一層自然なものに高めています。
もう一つのJointパーツであるLegsJointの機能はもう少し簡単です。
プレイヤーのWASDの入力に合わせて接続されたパーツを各方向に45°傾けるだけ。それだけでロボットの移動に合わせて傾く脚部の挙動が再現できてしまいます。ちなみにLegsJointという名前がついていますが今回のサンプルロボットでは正確には足ではなく腰の可動にLegsJointを利用しています。足が動くようにLegsJointをつけるとJointパーツが二つ必要ですが、腰の部分で傾ければ一個のJointで済むことに制作中気が付いたので今回はそのように作成しました。もちろんLegsJointの名前の通り足の部分を稼働させるために関節パーツを利用しても問題はありません。
GunパーツはTestGunと名前を付けた円柱のプレハブにYプラス方向に向けて弾を生成して発射させるだけの簡素な構造になっています。今のところ丸い球状の弾を発射するだけのシンプルなものですがこのスクリプトを元に今後は色々な武器を追加出来たらいいと思っています。
今回のアップデート内容を実装するために、裏では大掛かりな修正作業が必要になりました。
とくに大変だったのはJoint系パーツの実装のためにロボットの親子構造を「Core・Parts」の二段構造から「Core・Section・Parts」の三段構造に変更させたことです。
UnityでJointを実装するには様々な方法があります。一番手っ取り早いのはUnity標準のJoint系コンポーネントをパーツにアタッチして物理演算を利用した関節システムを作成することです。物理演算のされている関節システムをイチから作ったらどうなるかわかりませんがUnityでは最低でも二つのオブジェクトにRigidbodyコンポーネントをアタッチした上で関節軸となる方のオブジェクトにJointオブジェクトをアタッチして各種設定を行えばそれだけでJointが作成できます。
しかしこの機能、スペースロボクラの関節システムとして利用するには無視できない欠陥がありました。オブジェクト同士を物理演算のついた物体として扱う仕様上、一定以上の加速度でロボットを動かすとつながっているオブジェクトが剥離してしまうのです。Unityで一番自由度の高いJointコンポーネントであるConfigurable Jointの設定を色々試したりもしましたが私の技術力ではこの問題はどうしようもありませんでした。
こうなると残る手段はロボットのパーツのTransformを直接スクリプトで編集して自力で関節システムを作る以外にありません。この時まず利用しようと考えたのがUnityの親子構造システムを利用して関節を駆動させることです。
Jointシステムを作るとき最低限必要な機能は「接続されたオブジェクトが根元のオブジェクトの動きに対して追従すること」です。この機能だけなら接続先のオブジェクトを根元のオブジェクトの子オブジェクトとして扱うことで簡単に実装できます。あとは接続されたオブジェクトを回転させる機能を実装すればそれでおしまいです。
ところが、この方法でJointを実装するとロボットの関節が第二、第三と増えるにつれて階層が無限に深くなってしまいます。このような決まりを持たない不定形の親子構造というのはゲームを今後製作する上で大変都合が悪く、またJsonファイルにロボットのデータを保存するときにもJsonファイルの扱いが特に苦手な自分には理解不能なエラーを連発してしまい、最終的にロボットの階層構造を「Core・Section・Parts」の三層構造に固定することにしました。
Coreはロボットを構成するあらゆるオブジェクトを子オブジェクトとしている実体を持たないemptyオブジェクトです。ロボットの操縦系を制御するRobotControllerスクリプトやRigidbody、そしてロボットの組み立てシステムを担当するRobotMaker2スクリプトもここにアタッチされます。
その下にあるのがSectionオブジェクトです。これが今回追加された新しい階層を担当するemptyオブジェクトで、複数のPartsオブジェクト(ブロック)を束ねて腕や足、胴体など大まかなロボットの部位を構成するオブジェクトです。このオブジェクトがJointオブジェクトの間接軸にもなっていて、このオブジェクトを追従させたり回転させることでロボットの腕や足を動かすことを可能にしています。
このSectionを実際に操作するのがJointパーツのスクリプトで、Jointパーツは設置されたときや機体データがロードされたときに特定の場所にSectionが存在しているかどうかを自動で調べ、存在するならそれを取得し操作できるようにします。
今個人的に悩んでいるのは「システム開発ってやりだしたら永遠に終わらなくない?」ということです。
プログラミングをやったことがある人ならわかるかもしれませんが、個別に機能を持ったプログラムを書くのは難しいかもしれませんが面倒ではないです(比較的)他のコードとの連携を気にせず一つのスクリプトに集中して取り組めばいいだけだし、プログラムや数学の難しい要素にぶつかることはあっても解決方法が分かってしまえば短時間でコードは書けます。
問題はそうやって作った個別のプログラムを一つのゲームとして動かすためのシステム開発です。これは個別のプログラムを持ったプログラムを書くのとは逆でそこまで難しくはないですがひたすらに作業量が多い。一つのプログラムの面倒を見るのも手間なのに複数のプログラムの面倒をみたり連携させたりしないといけないし、何よりやり始めたら永遠に新しい課題が生まれてくるので全く終わりが見えません。Unityでゲーム開発をしていて画面の描画や各種判定処理、物理演算など多くの部分を代行してもらってこれなのですからC++でイチから3Dゲームを開発し始めたら恐ろしいことになると思います。
そんな感じでシステム開発は適当なところで見切りをつけないと一生終わらないので、この後Jsonファイルのセーブデータを複数扱えるシステムを製作したらそこでいったん切り上げるつもりです。
その後の予定ですが……実はこのゲーム、近日行われる大学のイベントの出し物として提出する予定なのですが、そのためにずっと見ないふりをし続けてきた企画書の作成やグラフィックの改善をしようと思っています。例えばこのゲーム、効果音やBGMの設定をしていないためずっと無音の状態で動いているのですがさすがに出し物として出すゲームが音すら出ないのはどうかと思うわけです。それにeffectの類も全くないので、できればスラスターの噴射エフェクトくらいは実装したいと思っています。
あとはUIです。イベントで見せるならボタンの見た目もUnityの標準データのままではいけませんね。一応やろうと思えばUI素材はイラストレイターなどで自作できるはずですが、UIデザインについて考えるのは初めてなのでどうなるかはまだわかりません。
次に制作する記事ではそうした部分についてまとめられたらいいなと思っています。