【Unity】Invokeとは?設定した時間が経過したらメソッドを呼び出す

Invokeとは? Unity

こんにちは、ともくんのゲーム作り部屋にようこそ!

このページでは、

「UnityのInvokeメソッドってなに?」

「Invokeはどんなことができるの?」

というお悩みの方に向けた内容となっています。

Unityでは、Invokeというメソッドを使って、指定した時間が経過したらメソッドを呼び出すという遅延処理を作ることができます。

例えば、5秒後に爆発する処理を作ったり、10秒経過したらオブジェクトが動き出すというような仕組みをInvokeメソッドで作ることができます。

Unityで同様に遅延処理を作れるコルーチンの機能と比べると、Invokeは複雑な遅延処理は作れないもののコルーチンよりも簡単に利用することができるという特徴があります。

そこで、このページでは、UnityのInvokeメソッドについて、どんなメソッドなのか、またコルーチンとの違いや使い方までをまとめていきます。

この記事を書いた人

ゲーム作りを学び始めた一児のパパです。
このブログは、子供から「ゲームを作ってみたい!」と言われ、非プログラマーでゲーム作りをしたことない僕が、ゲーム作りの本を読んで独学でゲーム開発を学んでいるブログです。
同じように初めてゲーム作りをしている方と一緒に学んでいけるようなブログに出来たらいいなと思っています。
また、「このコードはおかしい」とか「もっと良い書き方があるよ!」などあれば、どんどん指摘して頂けると助かります。

Invokeとは?

まずは、Invokeメソッドがどういうものなのか紹介していきます。

設定した時間の経過後にメソッドを呼び出してくれる

Invokeメソッドとは、時間とメソッドを指定することで、その時間が経過したらメソッドを呼び出してくれるという処理を行います。

例えば、通常は、UnityのStart()の中でメソッドを記述した場合、ゲームが起動しオブジェクトが読み込まれて、すぐにそのメソッドの処理が行われることになります。

しかし、このメソッドを記述する時に、Invokeを使って呼び出してあげることで、ゲームが起動しオブジェクトが読み込まれて、指定した時間が経過したタイミングで、そのメソッドが呼び出されて処理が行われるようになります。

このように、Invoke指定した時間分を遅らせてからメソッドを呼び出すことができるメソッドです。

Invokeとコルーチンとの違い

Unityでは、Invokeと同じように遅延処理を行う際にコルーチン(Coroutine)という機能を使うことがあります。

このコルーチンとは、処理を中断・待機して再開することができる関数のことで、Invokeと同じく特定の時間を経過させた後に、処理を行うということができます。

そして、Invokeと違う点として、コルーチンは複雑な遅延処理を作るのに強いという特徴があります。

例えば、ゲームが起動してから5秒後に移動する処理が行われ、その処理の5秒後に消去するという処理を作る場合を考えてみます。

Invokeで作る場合は、ゲーム起動の5秒後に移動処理を行うメソッド10秒後に消去する処理を行うメソッドをそれぞれ呼び出すということで実装出来ます。

しかし、この遅延処理の種類や数が増えてくると、時間の計算などスクリプトの記述がよりややこしくなっていくのが分かります。

一方で、コルーチンを使う場合は、5秒経過したら移動処理を行い、その後さらに5秒経過したら消去処理を行うといった形で、それぞれの処理の流れで作っていくことになるので、遅延処理が複雑になっても記述しやすくなります。

そのため、

  • Invoke ⇒ 単純な遅延処理を簡単に記述できる
  • コルーチン ⇒ 複雑な遅延処理でも流れのまま記述できる

という違いがあります。

なお、遅延処理を作る際は、他にもUniTaskという機能も使われることが多くおすすめです。

Invokeの使い方

ここからは、Invokeの使い方について紹介していきます。

引数で時間と呼び出すメソッドを指定する

Invokeを使う際は、以下のように引数で呼び出したいメソッドと経過させたい時間(秒)を指定して使います。

Invoke("methodName", time);

methodName:呼び出したいメソッド名(string型)
time:経過させたい秒数(float型)

第1引数にInvokeで呼び出したいメソッド名string型で指定します。

string型となるので、メソッド名の指定は「”」で挟んで記述してあげます。

そして、第2引数に経過させる秒数float型で指定してあげます。

起動して5秒後にオブジェクトを移動させる処理を行う

ここでは、実際にInvokeメソッドを使って、以下のオブジェクトをゲーム起動後に5秒経過したら移動させるという処理を作ってみます。

オブジェクトに以下のスクリプトをアタッチしていきます。

using UnityEngine;

public class Test : MonoBehaviour
{
    bool isMoving = false;  // 移動させるかどうかを判定する変数
    Vector2 target = new Vector2(6f, -3f);  // 移動先の座標を作成

    void Start()
    {
        Invoke("MoveStart", 5f);    // 5秒後にMoveStartメソッドを呼び出す処理
    }

    void Update()
    {
        Move();
    }

    void MoveStart()
    {
        isMoving = true;    // 変数をtrueに変更
    }

    void Move()
    {
        // 変数がtrueに変更された場合
        if (isMoving)
        {
            transform.position = Vector2.Lerp(transform.position, target, Time.deltaTime * 2f); // オブジェクトを移動する処理
        }
    }
}

まず、Startメソッドの中の10行目で、Invokeを使い5秒後にMoveStartというメソッドを呼び出す処理を作ります。

次に、18行目でMoveStartメソッドを作り、その中でisMovingの変数をtrueに変更する処理を行っています。

そして、Updateメソッドの中でMoveメソッドを呼び出し、このMoveメソッドの中の26行目から29行目でisMovingがtrueに変更されたら、Lerpメソッドによってオブジェクトを特定の座標まで移動させるという処理を行っています。

実際にこれでゲームを実行してみると、

ゲームが起動して5秒経過してから移動処理が行われているのが分かります。

Invokeの関連メソッド

ここまでInvokeメソッドの使い方を紹介していきましたが、Invokeと関連しているメソッドとして以下の3つがあります。

  • InvokeRepeating:一定間隔でメソッドを呼び出す
  • CancelInvoke:Invokeで呼び出す処理を取り消す
  • IsInvoking:Invokeが呼び出されているかどうかを判定する

ここでは、それぞれの3つのメソッドがどういったものなのか、使い方までを簡単に紹介していきます。

InvokeRepeating:一定間隔でメソッドを呼び出す

InvokeRepeatingは、Invokeと同じく設定した時間が経過するとメソッドを呼び出す処理が行われ、さらにその後指定した秒数ごとにそのメソッドの処理が繰り返し行われます。

InvokeRepeatingを使う際は、以下のように引数に繰り返して処理を行う間隔を秒数で追加指定します。

InvokeRepeating("methodName", time, repeatRate);

methodName:呼び出したいメソッド名(string型)
time:経過させたい秒数(float型)
repeatRate:繰り返して処理を行う間隔・秒数(float型)

例えば、ゲーム起動後5秒経過したらオブジェクトの向きが反転する処理が行われ、その後2秒間隔で反転処理が繰り返されるといった処理を作ってみます。

オブジェクトに以下のスクリプトをアタッチしておきます。

using UnityEngine;

public class Test : MonoBehaviour
{
    void Start()
    {
        InvokeRepeating("Turn", 5f, 2f);    // 5秒後にTurnメソッドを呼び出して、2秒ごとに繰り返す
    }

    void Turn()
    {
        transform.localScale = new Vector3(-transform.localScale.x, transform.localScale.y, transform.localScale.z);    // 左右反転する処理
    }
}

Startの中の7行目で、InvokeRepeatingを使って、ゲームが起動したら5秒後にTurnメソッドを呼び出す処理を行っています。

また第3引数の部分で、その後2秒ごとにTurnメソッドが繰り返し行われる設定にしています。

これでゲームを実行してみると、

5秒後に反転処理が行われた後に、2秒間隔で反転処理が繰り返されているのが分かります。

CancelInvoke:Invokeで呼び出す処理を取り消す

CancelInvokeは、Invokeで呼び出している処理に対して、キャンセルして取り消しの処理を行うメソッドです。

CancelInvokeを使う際、以下のように引数にメソッド名を指定することで、事前にInvokeでそのメソッドが呼び出されている場合は、その処理が取り消されることになります。

CancelInvoke("methodName");

methodName:取り消したいメソッド名(string型)

なお、引数を指定しない場合は、全てのInvokeによる処理をキャンセルすることができます。

例えば、先ほどInvokeRepeatingで作ったオブジェクトの反転処理に対して、スペースキーを押したら呼び出しが取り消される処理を追加してみます。

using UnityEngine;

public class Test : MonoBehaviour
{
    void Start()
    {
        InvokeRepeating("Turn", 5f, 2f);
    }

    void Turn()
    {
        transform.localScale = new Vector3(-transform.localScale.x, transform.localScale.y, transform.localScale.z);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            CancelInvoke("Turn");   // Turnメソッドの呼び出しを取り消す処理
        }
    }
}

Updateメソッドの中の19行目で、スペースキーを押した場合にCancelInvokeメソッドでInvokeRepeatingによるTurnメソッドの呼び出しを取り消す処理を行っています。

これでゲームを実行してみると、

スペースキーを押すと、反転処理が止まるようになっているのが分かります。

IsInvoking:Invokeが呼び出されているかどうかを判定する

IsInvokingは、Invokeによってメソッドが呼び出されているかどうかを判定する処理を行うメソッドで、呼び出されている場合はtrue、呼び出されていない場合はfalseを返します。

このIsInvokingを使うことで、まだ呼び出されていない場合に呼び出す処理を行うことができるので、Updateメソッド内でもInvokeを使うことができるようになります。

IsInvokingを使う際は、以下のように引数にメソッド名を記述して使います。

IsInvoking("methodName");

methodName:呼び出されているか知りたいメソッド名(string型)

例えば、スペースキーを押してから5秒後にオブジェクトを回転させるという処理を作ってみます。

using UnityEngine;

public class Test : MonoBehaviour
{
    Renderer ren;

    void Start()
    {
        ren = GetComponent<Renderer>();
    }
    void Update()
    {
        // Rotationメソッドが呼び出されていない時にスペースキーを押した場合
        if (Input.GetKeyDown(KeyCode.Space) && IsInvoking("Rotation") == false)
        {
            Invoke("Rotation", 5f); // 5秒後にRotationメソッドを呼び出す
        }

        if (Input.GetKeyDown(KeyCode.Space))
        {
            ren.material.color = Color.red;
        }
    }

    void Rotation()
    {
        transform.Rotate(0, 0, 45f);    // オブジェクトを45度回転する処理
    }
}

Updateの中の14行目で、if文の条件式でスペースキーを押した場合、かつIsInvokingRotationメソッドが呼び出されていない場合に、Invokeで5秒後にRotationメソッドを呼び出す処理を行っています。

ここではさらに分かりやすいように、21行目でスペースキーを押すと、オブジェクトの色が赤色に変化する処理を行っています。

これでゲームを実行してみると、

スペースキーを押して色が変わった後、5秒経過してからオブジェクトが回転する処理が行われています。

まとめ

このページでは、UnityのInvokeメソッドについて、どんなメソッドなのか、使い方までをまとめていきましたが、いかがでしたでしょうか?

Invokeメソッドは、指定した時間が経過したらメソッドを呼び出してくれる処理を行うメソッドです。

Invokeメソッドの引数で、呼び出したいメソッド名経過させる秒数を指定することで、時間が経過したらメソッドの処理が行われるようになります。

また、UnityではInvoke以外にも、コルーチンUniTaskといったものを使うことで、ゲーム内で待つという処理を作ることができます。

最後までお読みいただきまして、ありがとうございました!

コメント