強力の Callback プログラミング

こんにちは。開発担当のマットです。

最近、暇の時に、Unity というゲーム・エンジンで色々遊んでいます。
Unity で自由自在にゲームを作ることができ、武器を振り回して街を爆発させるゲームやゾンビー・ゲームやストラテジー・ゲームなど、色々作ったことはあります。

ところで、ゲームは割と複雑なものです。ビジュアルも、アニメーションも、効果音も色々ありまして、プログラムを正しく設計しないと、バグに繋がってしまいます。

従来の書き方

とても簡単な例でゲーム・プログラムの従来の書き方を紹介します。
例のゲームを、「マイ・ペット」と呼びましょう。このゲームにペットを育てることができます。
このゲームを作るには、データを持つクラスと、画面にペットを書き出すクラスは必要でしょう。

1. PetData クラス。
 このスクリプトの中に、ペットの色・サイズ・特徴など、全てのデータを記録しています。
2. DrawPet クラス
 このスクリプトは PetData のデータを使って、ペットを画面に描き出す(描画する)。

普通だったら、ゲームが開始されたら、DrawPet が PetData の中身を見て、ペットを画面に書き出します。

ところで、ゲームの中で「ピンク薬」という魔法なアイテムを使って、ペットの色が「ピンク」になった場合はどうしたらいいでしょう?DrawPet はペットを描き直さないといけませんが、データが変わったことにどうやって気づくでしょうか?

従来な方法は2つあります。

1. PetData の中のデータが変わる時、PetData は DrawPet のファンクションを呼び出す。(Function Call)
2. DrawPet は定期的に、PetData の中身が変わったかを確認する。(Polling)

ところで、どちらにも問題はあります。

Function Call の問題

データが変わった時に、DrawPet のファンクションを呼ぶことは大して悪くはないですが…
気をつけないと膨大してしまうプログラムの書き方です。

例えば、ゲームの中に「ペット詳細」の画面を追加しようと思った時、その「ペット詳細」画面を更新するファンクション・コールも必要になるでしょう。
それとも、色が変わった時、効果音を再生したい場合は?
アニメーションを実行したい場合は?

色のデータを変更するタイミングですべてのシステムにファンクション・コールをしないといけません。
そして、一つでも抜けたらバグ!

直感的ではありますが、問題ですね。

Polling の問題

確かに、DrawPet は PetData を確認したら、上記の問題は解決となります。

ただし、問題はタイミングとなります。DrawPet はいつ PetData を確認すればいいでしょうか?
一瞬で反応する仕組みを作りたければ、毎秒毎秒、何十回、何百回も繰り返しで PetData の中身を確認する必要が生まれてしまいます。

一つのペットなら問題ないかもしれませんが、ペットを増やそうと思ったら、その分の処理も増えます。
そして、DrawPetだけではなく、UI、効果音、アニメーションなど、それぞれのシステムは各々の PetData を連続的に確認する必要になりますね。

しかも、データはそれほど頻繁にかわらないので、無駄な処理ばっかり走っていますね。
ゲームがガタガタと遅くなってしまう恐れはあります。良くないですね。

Callback のチカラ

ここで紹介したいのは Callback の力です。

PetData は DrawPet などのファンクションを呼ぶことも良くないし、
DrawPet は PetData に毎回尋ねるのも、無駄な処理になりますので、
使えばいいのは Callback です。

PetData の方でファンクション参照先を登録できるようにすることです。
これを使って、DrawPet  はPetData に “RedrawPet” というファンクションを登録する。
DrawPet は “RedrawPet” のファンクションを実行するではなく、そのファンクションの参照先を PetData に登録するのだけです。

そして、PetData の方でデータが変わる時、PetData は登録された “RedrawPet” ファンクションを呼ぶことはできます。

このプログラミング方法を使うと、プログラマーはデータのクラスに、描画やUIや効果音やアニメーションのことを一切書くなくて大丈夫です。
それぞれのシステムはデータクラスにファンクションの参照先を登録をして、呼ばれるのを待つだけです。
「呼び返す」の感じですね。なので、Callback と言います。

ぜひ、次のプロジェクトで、Callbackプログラミングをお試しください。

コメント