ラムダ式とコールバック

Unity解説

動画で見たラムダ式っていったい?

ちょっと難しい話題だよね

この記事でラムダ式と用途を解説するよ!

※本記事はスタジオしまづさんの動画をもとにしています。ぜひ併せてご覧くださいませ

https://youtu.be/IQBVZRIJPyI

ラムダ式(lambda expression)

関数のラムダ表現です。C#はラムダ記号ではないんですが昔むかし発祥がラムダっぽい記号を使ってたのでラムダ式と呼ばれます。

通常、関数は、アクセス修飾子+型+名前+引数で構成されますよね。
こんなかんじです。

public void square(int x) 
    {
        return x * x; 
    }

一方、ラムダ式では

square = x => x * x;

のように表現されます。関数名もないし意味わかんないですね。ちなみに無名関数と呼ばれます。

これをどこで使うかというと、コールバック関数で使います。

コールバック関数

あまり馴染みのないワードが出てきましたね。残念ながらUnityではよく出てきます!

コールバック関数は何かの処理を後から差し込む仕組みです。

たとえば、友人が今から会いにきてくれるとしましょう。なんと友人は「行く途中になんか用事あればやってあげるよ!」と申し出てくれました。
あなたはジュースを買ってきてもらってもいいし、川の様子を見てきてもらってもよいです。これを指定することができます。

このとき、友人に対して指定する用事がコールバック関数です。

では、Unityの世界ではどんなときにコールバックが出てくるのでしょうか?

DoTweenにもあるコールバック

一例として、有名なアセットDoTweenで様々なコールバック関数を使えます。

※DoTweenはキャラなどを動かしたり揺らしたりするとても強力なアセットです

本当にいろいろできるアセットで、例えば敵にぶつかったときに上にちょっと上がってからヤラレたときのエフェクトを出してキャラを消滅させる、みたいなことができます。

上にピョンと上がるのはDoTweenのDoMoveを使います。
DoMoveには動作が完了したときに何か後続処理をさせることができます。それがOnCompleteコールバックです。

そうです、ここにキャラ消滅の処理を入れることができます。

DoTweenのOnCompleteの実例

キャラの消滅とかエフェクトは抜きにして、話を簡単にした実例を出してみます。

ここでは、動画と同じように四角形をDoTweenで動かした後にデバッグログを出すということをやってみます。

コードはこんなかんじです。

using UnityEngine;
using DG.Tweening;


public class Hoge : MonoBehaviour
{
    private void Start()
    {
        // 2s かけて右に3動く
        transform.DOMoveX(3f, 2f).OnComplete(Moved);
    }

    // コールバック関数
    private void Moved()
    {
        Debug.Log("moved");
    }
}

DOMoveXというのがDoTweenの移動の部分で、続くOnCompleteの部分が「DOMoveXが終わったら何をしてほしいか」を指定するコールバックを差し込むところです。友人に頼む用事の部分ですね。

ここではデバッグを出すだけの関数Movedを指定しています。ここを差し替えれば、ピョンと跳ねたあとにキャラ消滅というようなことができるようになるわけです。

このように、あらかじめ用事を受け付けられるようにだけしておいて中身を後で指定できる仕組みをコールバックといいます。

[PR] DoTween Pro

ラムダ式とコールバック

さて、ここでようやくラムダ式の使い道が出てきます。コールバックには関数名を指定する方法とラムダ式で指定する方法があります。

さっきのコールバックをラムダ式で書くと、こんな感じになります。

using UnityEngine;
using DG.Tweening;

public class Piyo : MonoBehaviour
{
    private void Start()
    {
        // 2s かけて右に3動く
        transform.DOMoveX(3f, 2f).OnComplete( () => Debug.Log("moved"));
    }
}

関数MovedがなくなってOnCompleteに直接デバッグ文を出していますね。見た目がとってもスッキリしました! 素晴らしい!

・・・ただ、スッキリするだけでワザワザこんな記法を使う必要はあるのかというと、最初のうちはそんなに必要性はないかもしれません。

Unityに慣れてきてコードの美しさに目がいったときにまた思い出してください。

まずはアプリを楽しんで完成させることが一番大事です!

ラムダ式の素敵な用途

それでも活用できる場面が無いわけではありません。ちょい関数なら宣言せずすっきり表現できることもあります。

たとえば、List型にあるFindAll関数はコールバックで指定した条件文にあう要素を取り出すのですが、ここを無名関数にすると少しハッピーになれます。

例として、動画と同じくリストから偶数を取り出したいとします。

まずはド直球に書いた場合。

    private void Start()
    {
        List<int> numbers = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

        List<int> evenNumbers = GetEvenNumbers(numbers);

        Debug.Log(string.Join(",", evenNumbers));
    }

    private List<int> GetEvenNumbers(List<int> numbers)
    {
        List<int> evenNumbers = new List<int>();
        for (int i = 0; i < numbers.Count; i++)
        {
            if (numbers[i] % 2 == 0)
            {
                evenNumbers.Add(numbers[i]);
            }
        }
        return evenNumbers;
    }

ザ・直球ですね。

これをラムダ式で書いて同じような動きにすると、

private void Start()
{
    List<int> numbers = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    List<int> evenNumbers = numbers.FindAll(num => num % 2 == 0);
    Debug.Log(string.Join(",", evenNumbers));
}

こうなります。とてもすっきりしますね。FindAllの中身がラムダ式で記述した無名関数です。

これはFindAllに指定するコールバックを無名にしているだけなので、判定する部分をふつうの関数にすることもできます。

その場合、こうなります。

    private void Start()
    {
        List<int> numbers = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        List<int> evenNumbers = numbers.FindAll(isEven);
        Debug.Log(string.Join(",", evenNumbers));
    }

    private bool isEven(int num)
    {
        return num % 2 == 0;
    } 

これでもド直球よりはスマートに書けていると思いますが、ラムダで書いた方がだんぜんキレイな感はあると思います。

このように、うまく使えばコードがとてもスッキリする、それがラムダ式です。

まとめ

本記事ではラムダ式とコールバックを概説しました。

ラムダ式とは無名関数を記述するための書き方で、コールバック関数をスマートに書きたいときに使うものでした。

コードの美しさが向上するのでうまくマスターして取り入れてみてください。

かわいい我が子にオリジナルアプリを!

コメント

タイトルとURLをコピーしました