目次
この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。
17新卒エンジニアがUnity関係で学んだことの備忘録を書きます。
はじめに
お初にお目にかかります、17新卒エンジニアの HN:inoooooocchi と申します。
私は4月からエンジニアとして入社し、とあるゲームプロジェクトに配属され、サーバー側(Ruby及びRuby on Rails)とクライアント側(Unity(使用言語はC#))の両方の実装を担当させて頂いております。
ところが私は、RubyもC#もUnityも、入社するまで(正確には3月にインターンシップで配属されるまで)一切触ったことがありませんでした。
そんな中、ここ2、3ヶ月で様々なことを学び、そろそろ整理しておきたいな、と思った矢先にDorubyに記事を書くことになりました。
従って私の記事では、私が仕事をしていて最も楽しい瞬間である「UnityでのUI制作」について、今まで学んだことの備忘録としての意味合いを兼ねてご紹介させて頂きます。
ご注意
本記事では、前章で述べた通りのUnity初心者中の初心者が試行錯誤して覚えた内容を載せています。
従って、凄腕Unityユーザーの方々の中には、「もっと効率的な方法があるのに…」「本当にユーザーの事考えてる?」「え?入社してから今まで何やってたの?w」と思われる方がいらっしゃるかもしれません。
優しい目で見守って頂けると幸いです。
前書き
- Unityって?
それでは、早速本題に入っていきましょう。…と言いたいところですが、「そもそもUnityってよく聞くけど、どういうもんなの?」という方がいらっしゃるかもしれません。(私も1年ぐらい前までそうでした。)
なので、かるーく説明したいと思います。
Unityとは、ユニティ・テクノロジーズという会社が開発した、ゲームエンジン及びゲーム開発用プラットフォームのことです。
とっても簡単に言えば、ゲームを作るための基盤を提供してくれる便利なツールってことです。
GUI(マウスなどを用いて操作可能な直感的インターフェース)によって、ゲームを構成するオブジェクトの配置やオブジェクトを動かすためのスクリプトの設定が可能で、なんならプログラミングが一切出来なくてもゲームが作れてしまうという話もあります。
(もちろん、自作のスクリプトを用いることでさらにゲームの幅が広がります)
PC(Windows / Mac / Linux)、スマートフォン(iOS / Android)、さらにはPS4などのゲーム機、(Unityのプラグインを搭載した)Webブラウザなど、様々なプラットフォームに対応しているのも大きな魅力です。 - UIについて
ゲームを遊ぶためには、ユーザー(プレイヤー)が操作をする必要があります。
もちろん、ユーザーがゲームを遊びやすくするために、開発側はなるべく見やすく・分かりやすく・操作しやすいようなUIを用意してあげなくてはなりません。
例えば、1つのゲーム画面に全部で50個のボタンを配置する必要がある場合、「うまく入りきらないからめちゃくちゃ重なってるけど、頑張ってタップしてくれよな!」なんてUIは、「本当に遊んでもらう気があるのか?」と疑いたくなります。
そこで、今回の記事では、そのようなふざけた画面を作らないために、「たくさんのオブジェクトを並べる」UIの作り方を書いていきます。
1. SceneとCanvasの作成
まず最初に、Unityでオブジェクトを配置するためには、SceneとCanvasが必要になります。
用語解説
Scene: 「.unity」という拡張子のファイルで、これが1つの画面に相当します。
たくさんのScene(画面)遷移を繰り返し、ゲームが進行していきます。
(例:タイトル→メニュー→ステージ選択→ステージ→リザルト→ステージ選択…)
Canvas: Scene上にUIオブジェクトを配置するための、地盤となるオブジェクト。
まずはSceneを作ります。Unityを開いたら、File -> New Sceneで、Untitledという無名のSceneが作られます。
作ったばかりの新しいSceneには、Main Cameraというカメラオブジェクトのみ存在します。
次に、Canvasを作ります。Hierarchyの上で右クリックし、UI -> Canvasを選択します。
すると、Canvas(とEventSystem)が生成されます。EventSystemはUIの動作を管理する偉いオブジェクトで、これが無いとクリックや文字入力、タップ操作などが反応しなくなってしまいます。消さないようにしましょう。
さて、このCanvasには、いろいろな仕組みが備わっています。Inspectorウィンドウで、選択したオブジェクトの情報を確認することができます。
![Inspectorウィンドウでオブジェクトの詳細情報を確認](https://doruby.jp/uploads/assets/793/6601e473d7c3c390668f40958c9a4506.png)
![Inspectorウィンドウでオブジェクトの詳細情報を確認](https://doruby.jp/uploads/assets/793/6601e473d7c3c390668f40958c9a4506.png)
最初の設定として、カメラから見える位置にCanvas及びCanvas上のオブジェクトが来るようにします。
Canvas という機能のRender Modeという設定を選択し、デフォルトの「Screen Space – Overlay」から「Screen Space -Camera」にします。
![Render Modeを変更](https://doruby.jp/uploads/assets/794/8317c0320c3b72b572f3d442964a21ab.png)
![Render Modeを変更](https://doruby.jp/uploads/assets/794/8317c0320c3b72b572f3d442964a21ab.png)
Render CameraがNoneのままでは意味がないので、Sceneにもともと存在していたMainCameraをアタッチします。
アタッチとは、スクリプトやオブジェクトを別のスクリプトやオブジェクトの構成要素に追加し、アタッチされた側から干渉できるようにするための行為です。
今回の場合、MainCameraをCanvasにアタッチすることで、CanvasはMainCameraを認識し、使うことが出来ます。
ドラッグ&ドロップで、HierarchyウィンドウにあるMainCameraを、InspectorウィンドウにあるRender CameraのNoneの部分に持って行きます。
すると、無事カメラの設定が出来ました。
これで、Sceneの作成とCanvasの作成は完了です。ようやくUIを作っていけます。
2. オブジェクトを並べる領域を作る
それでは、オブジェクトを並べる領域をUnity上で作成します。
早速、先ほど作成したSceneのCanvasに、「オブジェクトを並べる領域」のオブジェクトを作ります。
Canvasの上で右クリックし、Create Emptyを選択します。
![Create Emptyで空のオブジェクトを作成](https://doruby.jp/uploads/assets/795/38804ff1d61c899fc602aee900b2541d.png)
![Create Emptyで空のオブジェクトを作成](https://doruby.jp/uploads/assets/795/38804ff1d61c899fc602aee900b2541d.png)
今回は、オブジェクトを並べる領域ということで、ObjectAreaなどの名前にしようと思いましたが、後々スクロール機能を追加したいので、InspectorウィンドウでScrollAreaという名前に変更します。
![ScrollAreaがCanvasの子オブジェクトとして存在](https://doruby.jp/uploads/assets/796/8934c53b8b04f26c5b486d28c4014b5d.png)
![ScrollAreaがCanvasの子オブジェクトとして存在](https://doruby.jp/uploads/assets/796/8934c53b8b04f26c5b486d28c4014b5d.png)
![ScrollAreaのサイズを変更](https://doruby.jp/uploads/assets/797/b61a2622cbe6c1f6164e24039afd7139.png)
![ScrollAreaのサイズを変更](https://doruby.jp/uploads/assets/797/b61a2622cbe6c1f6164e24039afd7139.png)
ここで、Inspectorの座標値の左側に、四角形の記号のようなものが見えると思います。
これは、Anchor(アンカー)といい、親オブジェクト(Canvas)に対して子オブジェクト(ScrollArea)の基準点がどこなのかを表しています。
現在は中央に設定されているため、ScrollAreaに取っての基準点(0 , 0)が、Canvasの中央座標になっていました。それを左にずらしたので、x座標が-160という値になったわけです。
本来ならプラットフォームごとの画面サイズの差を考え、このAnchorを調整しx,y座標が基準点から大きくずれないようにするべきですが、今回は省きます。
このAnchorはUIのレイアウトを決める上で非常に大事なものなので、詳細は別の記事を設けて書きたいと思います。
さて、これから、この300×300の領域にオブジェクトを並べていきます。
3. ScrollAreaの中身を作る
並べる領域が出来たので、今度はその中身を作ります。
今回は例として、何らかのステージを選択する画面を想定し、各ステージの名前が書いてあるボタンを作ります。
ボタンを作成するには、ScrollAreaの上で右クリックし、UI -> Buttonを選びます。
![SceneウィンドウでButtonが確認出来た](https://doruby.jp/uploads/assets/799/4851f931677451e8d6e6390d946eb29c.png)
![SceneウィンドウでButtonが確認出来た](https://doruby.jp/uploads/assets/799/4851f931677451e8d6e6390d946eb29c.png)
はい、ボタンが出来ました。Buttonって書いてありますし誰がどう見てもボタンですね。
本来なら、このボタンをクリックした時に別のSceneに遷移するなどのスクリプトを書いてアタッチするのですが、今回は省略します。
ちなみに生成直後のButtonには「Image」「Button」の二つの機能が最初から搭載されています。画像を変えたい時はImageのSourceImageに画像をアタッチすれば変更できます。(今回は省きます)
名前が「Button」じゃ寂しいので、適当に「StageButton」にしておきます。
同様に、ボタンに書かれている文章も「Button」じゃ何のボタンかさっぱりわからないので、適当にステージ名を入れてみます。
HierarchyのStageButtonの横に、▶︎があるのが確認できますよね。ここをクリックすると、Buttonの子オブジェクトを確認できます。
![▶︎ をクリックして子オブジェクトを確認](https://doruby.jp/uploads/assets/800/1b09e264e6018c21488752971649f712.png)
![▶︎ をクリックして子オブジェクトを確認](https://doruby.jp/uploads/assets/800/1b09e264e6018c21488752971649f712.png)
また、領域の横幅が300pixelなので、違和感がないようにボタンの横幅も280pixel程度にしておきます。
![ボタンのサイズを調整](https://doruby.jp/uploads/assets/801/ed0e417ffb54367e4c1eefa7b49e7443.png)
![ボタンのサイズを調整](https://doruby.jp/uploads/assets/801/ed0e417ffb54367e4c1eefa7b49e7443.png)
これで、押してもうんともすんとも言わないボタンが出来ました。
今回の趣旨はボタンを押すことでは無く、ボタンを並べ(て、スクロールさせ)ることなので、並べるためにボタンを大量生産しましょう。
StageButtonの上で右クリックし、Duplicate(複製する)を選ぶと、ボタンが複製されます。
もちろん、CopyしてPasteしても問題ありません。何度もやるのが面倒な人はCtrl + C -> Ctrl + Vしまくるといいでしょう。
![StageButtonを複製](https://doruby.jp/uploads/assets/802/ecf7c4562d7ebeac4b96bcfab3701a8a.png)
![StageButtonを複製](https://doruby.jp/uploads/assets/802/ecf7c4562d7ebeac4b96bcfab3701a8a.png)
![10個まで増やしてみた](https://doruby.jp/uploads/assets/803/f04f83d1722e9e19b84934517a27a824.png)
![10個まで増やしてみた](https://doruby.jp/uploads/assets/803/f04f83d1722e9e19b84934517a27a824.png)
というわけで、StageButtonを9個増やして合計10個にしてみました。
![10個あるはずなのに1個しか表示されない](https://doruby.jp/uploads/assets/804/2c2c07e64ebd170356df39146df8d532.png)
![10個あるはずなのに1個しか表示されない](https://doruby.jp/uploads/assets/804/2c2c07e64ebd170356df39146df8d532.png)
…が、何故か表示されているボタンは1個だけです。何故でしょう?
答えは簡単、「元のStageButtonの座標まで丸ごとコピーしてるから」ですね。つまり、1個にしか見えないStageButtonには10個のStageButtonが重なってしまっています。
「え、じゃあオブジェクトを複製するたびに手入力で座標をずらしていかなきゃいけないの!?」
もちろん、Unityには便利な機能があるのです。先輩に教えて頂いて、Unityの力ってスゲー!ってなりました。次の章でご紹介します。
4. Vertical Layout Groupを使ってみよう
その便利な機能とは、「Vertical Layout Group」という機能です。
どんな機能か説明する前に、まずは試しに使ってみましょう。
…と、その前に、機能の効果を体感しやすくするために一度複製したボタンを全て削除してください。
複数選択して右クリックでDeleteすれば一発です。
さて、StageButtonの親オブジェクトであるScrollAreaオブジェクトのInspectorをご覧ください。
見事に何もないですね。そりゃそうです、Create Emptyで空のオブジェクトを作りましたから。
オブジェクトに新たな機能を追加する場合、Add Componentをクリックします。Add Componentでは、Unityに標準で備わっている機能や、自作したスクリプトなど、様々な構成要素(Component)を追加できます。
![Add Componentで機能を追加](https://doruby.jp/uploads/assets/805/9f67e89a449bdea4f697aee15909ac56.png)
![Add Componentで機能を追加](https://doruby.jp/uploads/assets/805/9f67e89a449bdea4f697aee15909ac56.png)
![Vertical Layout Groupを追加](https://doruby.jp/uploads/assets/806/2c9f8711659ef997db6bfd878c820fbd.png)
![Vertical Layout Groupを追加](https://doruby.jp/uploads/assets/806/2c9f8711659ef997db6bfd878c820fbd.png)
何故か大きくなりました。
これはVertical Layout Groupの仕様であり、本記事の目的として不適切な動作なので、元に戻しましょう。
InspectorのVertical Layout Groupで、Child Force ExpandのWidth、Heightのチェックを外しましょう。
![Child Force Expandのチェックを外した結果](https://doruby.jp/uploads/assets/807/9e52d05ab6aa64a989807e086e44f172.png)
![Child Force Expandのチェックを外した結果](https://doruby.jp/uploads/assets/807/9e52d05ab6aa64a989807e086e44f172.png)
何故か小さくなりました。(左上)
焦らないでください、これもそういう仕様なのです。
Vertical Layout Groupは、子オブジェクトのサイズを自動で調整してしまうのです。
もともとのサイズを維持したい場合、子オブジェクトに手を加える必要があります。
![Layout Elementを選択](https://doruby.jp/uploads/assets/808/cd0ca01d920bbcda6cc0b3cac4427e86.png)
![Layout Elementを選択](https://doruby.jp/uploads/assets/808/cd0ca01d920bbcda6cc0b3cac4427e86.png)
すると、このようなものが追加されます。
![Layout Element設定](https://doruby.jp/uploads/assets/809/0116ecb7d0a3cc26a88f8bfe9b56d78d.png)
![Layout Element設定](https://doruby.jp/uploads/assets/809/0116ecb7d0a3cc26a88f8bfe9b56d78d.png)
![280 x 30を記入](https://doruby.jp/uploads/assets/811/0ee95e39ff0990616e608be5e4ed3b72.png)
![280 x 30を記入](https://doruby.jp/uploads/assets/811/0ee95e39ff0990616e608be5e4ed3b72.png)
すると…
![サイズが元通り](https://doruby.jp/uploads/assets/810/d395d62049e9d8dc97a206a11c51d94b.png)
![サイズが元通り](https://doruby.jp/uploads/assets/810/d395d62049e9d8dc97a206a11c51d94b.png)
あれほど縮こまっていたStageButtonが、Layout Elementの力により、本来のサイズ(=先ほど設定したサイズ)を取り戻しました。
Layout Elementは、Vertical Layout Groupや、後述するHorizontal Layout Groupなど、
「子オブジェクトのサイズを自動で調整してしまう機能」に対し、「このサイズにしろ!」と強制できる機能なのです。
ちなみに、StageButtonが左上に寄ってしまっているのは、ScrollAreaのVertical Layout GroupのChild AlignmentをUpper Centerにすれば中央に戻せます。
![Upper LeftからUpper Centerに](https://doruby.jp/uploads/assets/812/a3871452127fb99b511eddf6fcbb0201.png)
![Upper LeftからUpper Centerに](https://doruby.jp/uploads/assets/812/a3871452127fb99b511eddf6fcbb0201.png)
さらに、ScrollAreaに、「Content Size Fitter」という機能を追加します。
その後、Vertical Fitの部分をPreferred Sizeに設定してください。
![Content Size Fitter導入](https://doruby.jp/uploads/assets/813/70f08591929f07a4e5e16fcf7d66008d.png)
![Content Size Fitter導入](https://doruby.jp/uploads/assets/813/70f08591929f07a4e5e16fcf7d66008d.png)
Content Size Fitterは、そのオブジェクトのサイズを、全ての子オブジェクトのサイズに合わせて自動で変化させてくれる機能です。これが無いと、子オブジェクトを複製しすぎた場合、ぎゅうぎゅう詰めになって子オブジェクトが潰れて表示されてしまいます。
さて、これで準備は整いました。Vertical Layout Groupは、ただ単に「子オブジェクトのサイズを勝手に変えてめちゃくちゃにする機能」ではなく、ここから彼(?)の本領が発揮されます。
先ほどと同じように、StageButtonを10個ほど複製してみてください。
![StageButtonが並ぶ](https://doruby.jp/uploads/assets/814/380af808c48a014bbdd97c487d35e858.png)
![StageButtonが並ぶ](https://doruby.jp/uploads/assets/814/380af808c48a014bbdd97c487d35e858.png)
Vertical Layout Groupは、子オブジェクトを縦方向に自動で整列させる機能です。
同様に、Horizontal Layout Groupは、子オブジェクトを横方向に自動で整列させてくれます。
このようにして、無事に(?)ボタンを縦にたくさん並べることが出来ました!
ただし、この状態で複製し続けると…
はみ出ます。(※Unity上のGameウィンドウです)
ここで、スクロール機能が必要になってきますね。
しかし、今回の記事がかなり長くなってしまうため、それはまたの機会にご説明いたします。
5. 今後の課題&まとめ
今回は、オブジェクトを並べる際の基礎の基礎をまとめてみました。
今回作った機能を実際のゲームで運用させるためには、まだまだ課題があります。
- スクロールして、はみ出た部分をクリックできるようにする
- 「Stage1」の文字列を、Stage2、3、4…のように自動で変えたい(Prefab、スクリプトの使用)
- StageButtonをクリックした時に、何らかの処理を発生させる(スクリプトの使用)
次回からは、これらの課題を解決していきたいと思います。
このように、私の記事ではUnityによるUI作成をまとめて行きたいと考えていますので、
今回の記事を読んでUnityに興味が沸いた方、分からないことが解決した方(いるかな?)などなど、今後ともよろしくお願いします。
以上、17新卒エンジニアのinoooooocchiでした。