【Unity】Prefabで生成したインスタンスのメソッドを呼ぶ

スポンサーリンク

Unityで落ちゲーを作ろうとしていて、ブロックの消去アニメーション的な事をやりたくなりました。
そこで、試しにブロックに状態を持たせて、その状態が”消去中”になっていたらブロックを小さくしていく方法を考えます。

※ これはUnityやゲーム開発の勉強中での覚書的なTips的なことをツラツラと書く記事です

スポンサーリンク

呼び出すメソッド

ブロックに紐づけるオブジェクトのコードはこんな感じ

int型(enumの方が良いかな?)のstatus変数を用意して、その値によって更新(Update)の時の処理を行うだけです

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

public class Block : MonoBehaviour
{
    // ブロックの状態
    // 0: 初期状態、1: 落下中、2: 消去中、3: 削除待ち (仮決め)
    int status = 0;

    private int count = 0;

    void Update()
    {
        if (status == 2)
        {
            // 消去処理(20フレーム毎に小さく)
            if (count % 20 == 19)
            {
                // 75%ずつ小さくする
                Vector3 scale = transform.localScale;
                transform.localScale = new Vector3(scale.x * 0.75f, scale.y * 0.75f, scale.z * 0.75f);
                // サイズが最小になったら、状態を削除待ちにする
                if (scale.x < 0.1) SetWaitDeleteState();
            }
            count++;
        } else if (status == 3)
        {
            // 完全に消える時に何かしたいなら、ここでやる
        }
    }

    public void SetFallingState()
    {
        SetStatus(1);
    }

    public void SetDeletingState()
    {
        SetStatus(2);
    }

    public void SetWaitDeleteState()
    {
        SetStatus(3);
    }

    private void SetStatus(int status)
    {
        this.status = status;
    }
}

やりたい記述

やりたいのは、前述のクラスのSetWaitDeleteState() などを外部から呼び出すことです。
ですが…どうやって呼び出せるのでしょう?

// Prefabからインスタンス生成(blockPrefabはブロックのPrefab)
currentBlock = Instantiate(blockPrefab, new Vector3(0, 0, 0), Quaternion.identity);
// ↓ こんな感じで呼び出したい
currentBlock.SetDeletingState();

↑な感じをイメージしますが、これだとcurrentBlockはGameObjectクラスなので呼び出すことは出来ません。
なので、Blockクラスにキャスト出来ないか考えたのですけど……BlockクラスはGameObjectの派生では無いっぽいので無理でした。
↓ みたいな感じでやりたかった ……

(currentBlock as Block).SetDeletingState();

SendMessageメソッド

リファレンスを見ていたらGameObjectにSendMessageというメソッドがあります。
どうやらこれを使えば呼び出す事ができそう…

// これで、呼び出しできる
currentBlock.SendMessage("SetDeletingState");

これで、一応は呼び出す事ができました。
けど、これって安全な呼び出しではないし、パフォーマンスも悪そう…
(Javaのリフレクションに近い感じ?)
まぁ、これはこれで一つの方法として置いておいて、もっとちゃんと呼び出せる方法を調べました。

GetComponentメソッド

たぶん、Unityのスクリプトを書いていたらよく出てくると思われるメソッド…
GameObjectに付与しているコンポーネントを取得するメソッドですね。
最終的には、このメソッドで簡単に取得することができました。

Block block = currentBlock.GetComponent<Block>();
block.SetDeletingState();

GetComponent<T>()T部分にクラス名を入れるだけでOK!
これでやりたい事ができました。\ヤッタネ/
(もちろん、あらかじめ対象のPrefabにスクリプトを付与しておいてくださいね)

エラー処理

今回は、明らかに取得できることが分かっているので省いていますが、場合によっては取得できなかった場合のnullチェックをしておきましょう。

Block block = currentBlock.GetComponent<Block>();
// 取得できない場合はnullになるので、nullじゃ無い時にだけ実行する
if (currentBlock != null) block.SetDeletingState();

まとめ

オブジェクトに付与しているコンポーネントは GetComponent<T>() で取得できて、スクリプトもコンポーネントの1種なので、同様に取得できるという事ですね。
分かれば単純な事ですけど、理解していないと悩んでしまいますね。😓

スポンサーリンク