はじめに
こんにちは、株式会社ルーデル25卒の西村です。
本記事では、レアゾンホールディングスの新卒エンジニア研修で行われたゲーム研修の中から、ゲーム開発の効率を飛躍的に向上させるUnityの強力な機能、ScriptableObjectとInputSystemについてご紹介します。
目次
ゲーム研修って?
二週間の期間で下記内容の講義を受けました
- 環境構築
- Unity基礎
- インゲーム
- ビルド
- マスターデータ
- アウトゲーム
- ゲームの改造
本記事はインゲームに関する内容です。
ScriptableObjectとは
- ゲームデータや設定を効率的に管理できるデータコンテナの一種
- Scriptable(スクリプトで作れる)Object(データの入れ物)という意味
何ができる?
- いろいろな種類のアイテムや敵の追加が簡単にできる!
- パラメータ調整したい時にコンパイルを挟まず時間が節約できる!
- UnityのEditor上のGUIで触れるので、視覚的に分かりやすい!
使ってみよう!
実際に研修で作成したコードを使ってScriptableObjectの使い方を説明していきます。
実装したいもの
- 敵が落とすお金や、プレイヤーの武器などをアイテムとして実装したい!
- お金や武器は複数種類作りたい!
- 金額やダメージ量は調整しやすくしたい!
これらの要件を満たせるのが、ScriptableObjectです。
1. スクリプトを作成する
ScriptableObjectを作成するためには、まず設計図となるスクリプトを記述する必要があります。
スクリプト全文を表示
[CreateAssetMenu(fileName = "ItemData", menuName = "ScriptableObjects/ItemData", order = 1)]
public class ItemData : ScriptableObject
{
[SerializeField]
private string itemName; // アイテム名
public string ItemName
{
get { return itemName; }
}
[SerializeField]
private ItemType type; // アイテムの種類
public ItemType Type
{
get { return type; }
}
public enum ItemType
{
None,
Weapon,
Money,
Recovery
}
[SerializeField]
private Sprite itemIcon; // アイテムのアイコン
public Sprite ItemIcon
{
get { return itemIcon; }
}
[SerializeField]
private int itemValue; //アイテムの値(お金なら金額、武器ならダメージ量が入る)
public int ItemValue
{
get { return itemValue; }
}
}
要所について説明していきます。
以下のように、ScriptableObjectのスクリプトを作成する際には、ScriptableObjectを継承する必要があります。
public class ItemData : ScriptableObject
{
// ...
}
以下のように、作成したScriptableObjectをGUI上で追加するために、アトリビュートを追加します。
[CreateAssetMenu(fileName = "ItemData", menuName = "ScriptableObjects/ItemData", order = 1)]
public class ItemData : ScriptableObject
{
// ...
}
[CreateAssetMenu]
というアトリビュートを追加することで、Unity上でItmeDataというScriptableObjectを追加できるようになります。
方法について説明していきます。
2. 作成したItemDataをアセットとして追加する
先ほどコードに追加したアトリビュートのおかげで、以下のようにGUI上でアセットを追加することができるようになります。
3. 追加したItemDataに値を入れる
ScriptableObjectでは、以下のようにInspectorウィンドウ上で値を設定することができます。
ファイルに直接パラメータを書き込まなくてよいので、これによってコンパイルを挟まずにパラメータを設定できるようになります!
4. 作成したItemDataを利用する
ここから、ItemDataに設定したパラメータを利用する部分を作成します。
以下のようなスクリプトを書き、適当なオブジェクトにアタッチします。
[SerializeField]
private ItemData itemData; // アイテムデータ
void Update()
{
Debug.Log(itemData.ItemName);
}
ここで、hoge
というitemNameのItemDataを作成しておいて、アタッチ後にゲームを起動すると、以下のようなデバッグログが表示されます。
このように、ItemDataの値を取得することができます。
5. 値を変更してみよう!
ゲームを起動中に、アタッチしたItemDataのItemNameをhogehoge
と変更すると、デバッグログの値も以下のように変化しました。
ここでお気づきかもしれませんが、パラメータを変更した際に、コンパイルは挟んでいません。
このように、素早くパラメータを調整することを可能にできるのがScriptableObjectというものです。
ScriptableObjectまとめ
- ScriptableObjectとは、スクリプトで記述するデータの入れ物
- スクリプトが一つあれば、GUI上で簡単に複数個のScriptableObjectを作成することができる
- コンパイルすることなく、素早く値を変更することができる
InputSystemとは
ここからは、二つ目の便利な機能のInputSystemについて説明します。
InputSystemは文字通り、Input(入力)に関するシステムで、プレイヤーの入力操作を取得しやすくできる機能です。
何ができる?
- WASDや矢印キーでの操作を「移動」という入力にまとめることができる
- PlayStationなどのコントローラの入力も簡単に取得できる
使ってみよう!
InputSystemの使い方は、基本的にUnityのGUI上での操作がほとんどです。
実装したいもの
- スマホゲームによくある、画面上のジョイスティックでキャラクターを移動できるようにしたい!
- キーボードでもキャラクターを移動できるようにしたい!
1. InputSystemの追加
まず、PackageManagerからInputSystemをインストールします。
インストールできたら、InputSystem_Actions.inputactions
というファイルがAssets配下に生成されます。
これはそのまま使えますが、せっかくなのでそれは無視してInputSystemの追加方法から説明していきます。
InputSystem_Actions.inputactions
で早く使いたい方は手順3まで飛ばしてしまって構いません。
Projectウィンドウの適当なフォルダで右クリックして、Create/Input Actionを選択します。
InputActionsを選択すると、InputSystemのファイルが作成されます。
名前は適当で大丈夫です。
このようにInputSystemは簡単に追加することができます。ここから、取得する操作を設定していきます。
2. InputSystemの設定
1で追加したInputSystemをクリックするとInspectorウィンドウに詳細が表示されます。
まず左側のAction Mapsを設定します。
Action Mapsは、入力する操作を切り替えるためのもので、例えばプレイヤーの移動からメニューなどを開いたUIの選択でW
キーなど同じ入力キーを使いたい場合に、Action Mapsを切り替えることで移動かUI選択かを切り替えることができるものです。
今回はPlayerの移動のみ取得したいので、Playerという名前でMapを作成します。
Action Mapsの横にある「+」を押したらMap名をPlayerにしましょう。
Mapを作成すると、中央のActionsの項目にNew Actionが出てきます。この項目はプレイヤーに行わせたい操作を設定する項目です。
今回はプレイヤーを移動させたいので、New Actionという名前をMoveに設定しましょう。
名前を設定したら、右側のAction Propertiesを設定します。ここは、Moveというアクションの取得結果の型を決める部分です。
今回は移動方向を取得したいので、Action Typeをvalue
、Contorol TypeをVector2
に設定します。
そして、ActionsのMoveの配下にNo Bindingと表示されていますが、ここで移動するために使用する入力キーを設定していきます。
今回は画面上のjoystickとキーボード操作を取得したいので、まずjoystickを追加します。
No Bindingを選択すると、Action PropertiesにPathの設定項目があります。
このPathをJoystick/Stick
と設定します。
これだけで、このInputSystemはJoystickからの入力を取得できます。
次に、キーボードからの操作も取得します。今回はWASDで移動するものとします。
Moveと設定したActionの+を押すと、他の操作を追加できます。
ここで、Add Up¥Down¥Left¥Right Composite
を選択します。
すると、4つのBindingを持つ2DVectorが生成されます。これの名前はWASD
にしましょう。
この配下の4つのBindingにはそれぞれキーボードのWASDを設定します。各BindingでPathを選択した後に検索でW
などと打てばW[Keyboad]
があると思うので、それぞれ対応するキーを設定します。
これでInputSystemの用意は完了です。右上のSave Assetで設定を保存しましょう。
3. 画面上のJoystickの実装
InputSystemは設定できましたが、操作するJoystickをまだ実装していないので、実装していきます。
Joystickの背景とスティック部分の画像をUnityAssetStoreなどからImportしましょう。この画像はなんでもokです。
図のように空オブジェクト(Joystick)の配下に画像を配置します。
あとは、スティック部分のオブジェクトに、On-Screen Stickというコンポーネントをアタッチします。
Movement Rangeは、スティック部分が動ける範囲を設定する項目なので、適宜調整しましょう。
Control Pathは先ほどのInputSystemの設定と似てるので、サクッとJoystick/stickを設定しましょう。
ゲームを実行すると、スティック部分をジョイスティックのように動かせるようになります。
これで画面上のJoystickは実装完了です。
4. InputSystemの紐づけ
ここからは、設定したInputSystemを使って、どのオブジェクトを動かすかを設定します。
図に示すように、入力で動かしたいオブジェクトにPlayer Inputコンポーネントをアタッチします。そして、設定したInputSystemをPlayer InputのActionsにアタッチします。
InputSystemをアタッチすると、自動的にDefault Mapも設定されます。
これで、InputSystemの用意ができました。
ここからは、実際にInputSystemを利用するスクリプトを書いていきます。
5. スクリプトの記述
InputSystemから取得した操作でオブジェクトを動かすスクリプトを記述していきます。
手順2で取得する値をVector2に設定したことによって、Vector2で該当の操作を取得することができます。
スクリプト全文を表示
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerControler : MonoBehaviour
{
[SerializeField]
private PlayerInput playerInput; // PlayerInputコンポーネントへの参照
void Update()
{
Vector2 moveInput = playerInput.actions["Move"].ReadValue<Vector2>(); //InputSystemから操作を取得
moveInput.Normalize(); // 入力値を正規化して移動方向を取得
transform.position += (Vector3)moveInput; // 移動入力に基づいてキャラクターを移動させる処理を追加
}
}
スクリプトの解説をします。
以下の部分で、手順4にてPlayerオブジェクトにアタッチしておいたPlayerInputを参照します。
[SerializeField]
private PlayerInput playerInput; // PlayerInputコンポーネントへの参照
次に、以下の部分で手順2にて設定したMove
というアクションをVector2
として取得します。
Vector2 moveInput = playerInput.actions["Move"].ReadValue<Vector2>();
そして、以下の部分でプレイヤーを動かしています。
moveInput.Normalize();
transform.position += (Vector3)moveInput;
スクリプトは記述できたので、実際にこのPlayerControlerをPlayerにアタッチしましょう。
ここで、ゲームを実行して動かしてみると、画面上のJoystickでもキーボードのWASD
でもプレイヤーの移動ができていることが確認できます。
InputSystemを使うことで入力操作をMove
という操作に抽象化でき、コード上でどこからの操作かを気にする必要が無くなるのです。
さらに、InputSystemの入力キーの設定には様々な種類があり、PlayStationコントローラなどを設定すれば、PCに該当のコントローラを有線接続するだけで、コントローラを使ってゲームを遊ぶこともできます。
InputSystemまとめ
- InputSystemを使うことで、複数の入力を一つの操作にまとめることができる
- コントローラも接続することで、簡単にコントローラを使ったゲームを作ることができる
まとめ
今回の研修を通して、UnityのScriptableObjectとInputSystemがいかにゲーム開発を効率化し、柔軟性を高めるか実感できました。
本記事が、これからUnityでゲーム開発を始める方や、多様な入力デバイスに対応したゲーム開発を検討している方にとって、少しでも役立つ情報となれば幸いです。
最後までお読みいただきありがとうございました。
▼採用情報
レアゾン・ホールディングスは、「世界一の企業へ」というビジョンを掲げ、「新しい"当たり前"を作り続ける」というミッションを推進しています。
現在、エンジニア採用を積極的に行っておりますので、ご興味をお持ちいただけましたら、ぜひ下記リンクからご応募ください。