Unityでゲームを作ってみた
Unityで練習としてゲームを作ってみました。Unity周りのさまざまな仕組みは結構独特で面白いと思ったので、まとめておきます。
なぜUnityか
作ったもの
(ブログ貼付用) pic.twitter.com/PUgjkVrw3C
— threecourse (@threecourse) 2020年4月12日
以下で遊べます:
Topdown Defense | フリーゲーム投稿サイト unityroom
敵が画面下に到着しないようにプレイヤーキャラクターを攻撃させます。
タワーディフェンスを、タワーじゃなくてプレイヤーが攻撃するようにしたゲームです。
最小限の工数でゲームをとりあえず完成させようと思ったのですが、それでもいろいろ大変でした。
Unityによるゲームの作り方のメモ
参考資料
5年ぶり3回目くらいの挑戦ですが、主に以下を参考にしました。
Unityの教科書 Unity 2019完全対応版 2D&3Dスマートフォンゲーム入門講座
https://www.amazon.co.jp/dp/B07TNNTTYVUnityマニュアル
Unity ユーザーマニュアル - Unity マニュアル
開発画面
開発画面は以下のような感じで、主なウィンドウは以下のとおりです:
- プロジェクト(Project)
プロジェクトのファイルを管理するウィンドウ - ヒエラルキー(Hierarchy)
GameObjectの論理的な配置を行うウィンドウ - シーン(Scene)
GameObjectの空間的な配置を行うウィンドウ - インスペクタ(Inspector)
GameObjectのコンポーネントを操作するウィンドウ - ゲーム
ゲーム画面を表すウィンドウ
Unity - マニュアル: インターフェースについての学習
GameObject
Unityでは、GameObjectというものを配置してゲームを作っていきます。
- キャラクター・アイテムからライト・カメラなど、すべてがGameObjectである。
GameObjectに各種コンポーネントを付加することで、それぞれの役割になる。 - GameObjectには、C#などで記述したScriptを付加することもできる。
- GameObjectを階層構造を持たせて配置したり、グループ化して扱うこともできる。
Prefab
Prefabは、GameObjectのテンプレートのようなもので、アクションゲームのザコ敵など、同じようなオブジェクトを作成したい場合にはPrefabを作成します。PrefabをScriptからインスタンス化することで、動的に何個も作成することができます。
Script
ゲームロジックはC#などでScriptに記述します。GameObjectにScriptを付加して使用します。
- MonoBeheviorというクラスがあり、このクラスはUpdate関数を持つ。Update関数は一定間隔で呼び出され、ここに一定間隔ごとに行う処理を記述することで、ゲームの流れを作ることができる。
- キャラクタを表すGameObject、ゲームを管理するマネージャー的なGameObjectのどちらの場合でも、基本的にはMonoBeheviorを継承したクラスを持たせる。
- ユーティリティ関数などを持つ静的クラスを記述することもできる。 この場合、特にGameObjectに付加しなくても、プロジェクト内に含めておけばその静的クラスを他から呼び出せるようになる。
オブジェクト間の連携
ゲームのさまざまな処理を行うには、GameObject間で情報を伝達し、その情報に応じて反応させることが必要である。
GameObject間で情報を伝達するには、以下の方法がある:
- イベントの仕組みを利用し、イベント時に呼ばれる他のGameObjectのメソッドを登録する形にする
- 他のGameObjectのメソッドを直接叩く
いずれにしても、他のGameObjectを参照する方法が必要となる。以下の方法がある:
- インスペクタで他のGameObjectを指定して参照する
- Script内で名前や親子関係を指定して他のGameObjectを参照する
- 後述のシングルトンを利用してマネージャーのGameObjectを参照する
ゲームの枠組み
大枠としては、以下でゲームが構成される。実際には、UIとかカメラとか特殊効果とかもろもろやることがありますが・・
- ゲームの全体を管理するGameObjectを配置する
このGameObjectのScriptに全体的な流れや判定を記述する - キャラクターや建物のGameObjectを配置する
キャラクターを動かしたり、何かに反応させたい場合には、このScriptに記述する。 - ザコ敵などのPrefabを作成する。
他のScriptから呼び出されてこれらのPrefabがインスタンス化される。
その他開発まわり
UniRxというライブラリを利用し、リアクティブプログラミングというものを行うことができる。うまく使うと各クラスの処理を綺麗に分離できる。
- (参考) UniRx完全に理解した
- (参考) UniRx - GitHub - neuecc/UniRx: Reactive Extensions for Unity
UIで表示されるステータスを内部の値の変化に応じて変える場合にも、リアクティブプログラミングが便利。特に、UniRxのReactivePropertyを使うと、Vue.jsでバインドするような感じで書ける。
- 3DゲームでのUIは、3D画面とは別にUI用の2D画面を作成し、プレイ時にはその画面を重ねて表示する。
- マネージャーなどのクラスはあちこちから呼び出されるので、いちいちインスペクタで指定するのは面倒。ここで、シングルトンを利用することで、簡単に呼び出せるようになる。
(参考) Unityでよく使うデザインパターン - KAYAC engineers' blog - Script内でできるだけ処理を書くような開発も、Unityのヒエラルキーやインスペクタウィンドウを主にした開発もどちらもできる
アセットストアの利用
- Unityの魅力として、アセットストアからキャラクターのモデル、サウンド、エフェクトなどを購入できることがある
- 自分で一から作るのに比べて大幅に時間を削減することができそう。Unityは課金ゲー(?)
- 後述するTopDown Engineのように、半完成品みたいなアセットも販売されている。これらの中身を見て、コードの記述の仕方を学ぶのも有効。
Meshtint Studioのアセットを使ったのですが、他にもいろいろ種類があって使いやすそう assetstore.unity.com
slay the spire風のゲームを作れるアセットもある。ちょっと試してみたい assetstore.unity.com
ファイル管理
- ファイル名の変更や移動は、Unityのプロジェクトウィンドウ内で行う必要がある。そうしないと、保持されているメタデータの関係性が壊れてしまう。
- Gitで管理することができる。そのまま使うと、画像ファイルなどの重いファイルが管理されて大変なことになっていまうので、Git LFSを使うのが一般的らしい。
(参考) https://www.slideshare.net/kamera25/unity-git-lfs - アセットストアで購入したアセットはわりと好き勝手なパスにインポートされる。
デフォルトのパスの下に_MyAssetのようなフォルダを作っておき、その下に自作のAssetやScriptを入れるのが良さそう。
Topdown Engine
今回はこのアセットをベースに作成した。Corgi Engineなどのアセットを開発したMore Mountains作の、見下ろし型アクションゲームの半完成品のアセットです。
assetstore.unity.com非常に良く作られていて、ソースコードを読むのも勉強になる
結局、ライブラリの枠をはみ出ることをしようとすると、ライブラリをよく理解して、適宜修正して使わなくてはいけない。ボスを作ったときに、プレイヤーがボスの下に潜り込んでしまい、プレイヤーが移動床と判定されて計算がバグってボスが吹っ飛ぶという事象が発生した。ライブラリを読み込んでコードを修正しつつ、どこが悪さをしているかを探っていくことが必要だった。
キャラクターの移動は物理演算ではなく、内部的に与えられた力などを保持しておき、計算で求めている様子。確かに、物理演算に頼ると細かな処理が難しいかも。
Topdown Engineに同梱されているMMFeedbackというライブラリが本質ではないかと思った。攻撃をしたとき、敵に当たったとき、敵を倒したときにアニメーションや効果音、カメラへの衝撃などの形でフィードバックが与えられるかどうかで面白さがだいぶ違うように感じた。