gracetory’s blog

東池袋にある合同会社グレストリのエンジニアブログです

【Unity】はじめてのプレハブ

f:id:gracetory:20180412162308j:plain

こんにちは、冬以外の季節が大好きな東北産まれのプログラマgmatsuです。

暖かくなってとても過ごしやすい季節になってきましたね。

仕事では座ってばかりなので、運動不足を解消する為にも業務後や休日は近所をランニングしてます。

冬の間に貯めまくった欲望の塊(ぜい肉)を取り除くために日々走ったり歩いたり。

流石は欲望の塊、中々手強いです。

さてそんな訳で(どんな訳で)、今回はUnityのプレハブについて触れたいと思います。

シューティング、アクションゲームを作ろうとした時、敵とか弾の管理って皆さんどうしてますか?

クラス、構造体等、データを塊として管理する物を準備して、それを複数作成して…とかやりたいそこのアナタ!

Unityではプレハブを使うらしいですよ。

プレハブとは

Unityマニュアル:プレハブ

公式の説明ではこういう物なんだそうです。

扱い方はクラス、構造体と同様に、

  1. 定義
  2. 必要な数分だけ生成

という流れです。

例えば敵や弾のベースとなるプレハブを定義しておけばそれを必要な分だけ生成する事ができるので、10体でも100体でも敵が作り出せちゃうわけですね。

もちろん生成後は1つ1つの実体の座標、画像を別々に管理出来ますから、敵を10体分作ったとしても全て同じ敵ではなく、敵A、敵Bのようにパターンの違う敵を管理する事が可能です。

敵、弾を例に上げて解説はしましたが、RPGの村人、マップチップ等、同じタイプの物を複数作り出したのであれば、Unityではプレハブを使いましょう。

今回やりたい事

複数の画像(2D Object>Sprite)を表示する

この画像を今回はプレハブで用意します。

実行環境

Mac mini (Late 2014)

MacOS Sierra (10.12.2)

Unity (2017.1.1f1)

手順1. プレハブ化したいGameObjectの作成

まずHierarchyにプレハブ化したいGameObjectを作成します。

今回は2D画像を複数枚表示したいので、Hierarchyで右クリック>2D Object>SpriteでGameObjectを生成しましょう。

f:id:gracetory:20180412162423p:plain

Transform、SpriteRendererの2つのコンポーネントを持ったGameObjectが生成されました(今回は「chip」という名前にしています)。

このようなGameObjectを何個も作成して、敵画像を100体分...とかやってられないので、このオブジェクトをベースとしてプレハブを作成します。

手順2. プレハブの作成

HierarchyのプレハブにしたいオブジェクトをProjectにドラッグ&ドロップします。

f:id:gracetory:20180412162504p:plain

これでプレハブは完成です。

あっさり作れましたが、作るだけならこれで終わりです笑。

プレハブ化したオブジェクトのInspectorを確認してみましょう。

Transform等のSpriteに必要なコンポーネントを持ったプレハブを作ることが出来ています。

プレハブが出来たら元になったHierarchy内のGameObjectはもう必要ありませんので削除しちゃいましょう。

f:id:gracetory:20180412162526p:plain

後はこいつを使って、複数の画像を表示してみましょう。

※ちなみにプレハブは必ずResourcesフォルダに入れておきましょう。今回は「Assets/Resources/Prefabs」に入れています。

手順3. インスタンス化

プレハブを作っただけの状態では、プロジェクトを実行しても何も表示されません。

用意するだけではインスタンス(実体)が準備されていないからです。

Hierarchyにドラッグしてインスタンス化する事もできますが、やっぱり100個用意しろ…とか言われるとやってられません。

そこでスクリプトからインスタンス化する事で10個でも100個でも楽にインスタンスを準備する事ができるようになります。

今回はアプリが起動したらインスタンス化の処理が行われるようにしたいので、以下のようなスクリプトを用意しました。

// Assets/Scripts/Manager/ChipManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ChipManager : MonoBehaviour {
    GameObject[] _chip = new GameObject[3];

    /**
     * 初期化
     *
     * @access public
     */
    public void init() {
        // 生成
        create();
    }

    /**
     * チップ生成
     *
     * @access private
     */
    private void create() {
        // プレハブのロード
        GameObject chip = (GameObject)Resources.Load("Prefabs/chip");

        // 座標
        Vector2 pos;

        // 各チップのインスタンス化
        pos.x = 0.0f;
        pos.y = 150.0f;
        _chip[0] = Instantiate(chip, pos, Quaternion.identity);
        pos.x = 0.0f;
        pos.y = 0.0f;
        _chip[1] = Instantiate(chip, pos, Quaternion.identity);
        pos.x = 0.0f;
        pos.y = -150.0f;
        _chip[2] = Instantiate(chip, pos, Quaternion.identity);
    }
}

Chipを管理する為のマネージャとしてChipManagerを作成しました。

init()を呼ぶことでチップの生成、つまりプレハブのインスタンス化を行ってくれるようにしています。

Instantiate()にプレハブを渡すことでインスタンス化をしてくれています。

プレハブはロードする必要がありますので、先程Assets/Resource/配下に置いたプレハブのパスを指定しましょう。

ロードにはResources.Load()を使用しますが、このメソッドはResources/配下のファイルを読み込む為のものですので、Resources/以降のパスを指定すればOKです。

ロードしたらGameObjectとして受け取り、Instantiate()に座標データと共に指定しましょう。

こうすれば100個でも1000個でもオブジェクトの量産が可能になりますね。

でもこれだと100個なら100行近く書かないといけなくなるので、そこは配列やらファイル読み込みやらでよしなに修正して下さい。

また現状ではアプリが起動した時に上記処理を行ってくれませんので、次のようなマネージャも用意しました。

// Assets/Scripts/Manager/GameManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour {
    /**
     * エントリポイント
     *
     * @access private
     */
    void Start () {
        // ゲームオブジェクトのコンポーネントを取得
        ChipManager chip_manager = GetComponent<ChipManager>();   // チップ管理

        // チップ初期化
        chip_manager.init();
    }
}

あとはこのマネージャ達をAddComponentする為のGameObjectを次のようにHierarchyに用意します。

f:id:gracetory:20180412162550p:plain

HierarchyのGameManagerオブジェクトの生成と設定は以下の様に行っています。

1.Hierarchy場で右クリック>Create Emptyで作成

2.GameManagerをAddComponent

3.ChipManagerをAddComponent

この状態でアプリを実行した時の処理の流れは次のようになります

GameManagerのStart()が呼ばれる
↓
ChipManagerのinit()が呼ばれる
↓
ChipManagerのcreate()が呼ばれ、プレハブのインスタンス化の処理が呼ばれる

という事はこれでやっとインスタンス化をする事ができました! さっそく実行してみると...

f:id:gracetory:20180412162623p:plain

「chip(Clone)」が出来てる!

この「(Clone)」って付いているオブジェクトこそがプレハブをインスタンス化したGameObjectになります。

やったぜ!やっと表示され...

f:id:gracetory:20180412162638p:plain

何も表示されていません。

そりゃそうです、画像を設定してませんでした笑

記事も長くなってきたので、画像表示は次回にしたいと思います。

まとめ

マネージャの解説も入ってしまったので、プレハブだけの解説をまとめてみます。

・プレハブを使うメリット
同じジャンルの大量のGameObjectを管理する事が出来る。
11つオブジェクトの生成、設定を手作業で行わなくともスクリプトから一気に出来るので便利。
しかし各オブジェクトの座標等の個々のデータは、ファイル等を利用してうまく活用しないと、結局は大量行のソースコードが必要になる。
・プレハブの作り方、インスタンス化の仕方
1. プレハブを作る
2. スクリプトからインスタンス化する
・インスタンス化時の処理の流れ
1. プレハブをロードする
2. Instantiate()でインスタンス化する

表示する画像の事をすっかり忘れていたので、こちら次回の記事で書きます笑。

せっかくなのでSpriteAtlasを使用して、画像の管理をしやすくしてみたいと思います。

それではまた。

★2018/05/07 追記しました! ↓↓↓

techblog.gracetory.co.jp