UnityのJavaScriptでクラスの作成と継承、インタフェースの作成

今回はUnityのJavaScriptでクラスの作成と継承、インタフェースを作成する方法をやりたいと思います。

今までの記事でクラスを使った事もありましたが、あまり突っ込んで解説をしていなかったので、今回はサンプルを使って動作を確認していきます。

JavaScriptでスクリプトを組んでいるとなかなかクラスを作成しませんが、クラスを使うとUIのイベント受け取りをする時にEvent Triggerコンポーネントを追加してイベント処理関数を指定していた個所をインタフェースの実装という形で作成する事が出来ます。

通常のJavaScriptでクラス的なものを作ろうとすると結構面倒くさい事になりますが、
UnityのJavaScriptではJavaで作成するクラスと作成方法が同じです。
Javaをやった事がある方はほとんど同じだなと感じるはずです。

スポンサーリンク

クラスを作成

ではさっそくクラスを作成していきます。

通常通りJavaScriptのファイルを作成します。
今回は名前をHumanという名前にします。

これ以降はしばらくクラスの作成の仕方なので、オブジェクト指向プログラムを学んだ方は飛ばして結構です。

オブジェクト指向プログラムを学んだ事がある方はわかると思いますが、クラスはファイル名と同じ名前にします。

Humanクラスが保持する値はprivateにしHumanクラスからしかアクセス出来ないようにします。
Human(人間)クラスはname(名前)とage(年齢)プロパティを持ちます。

クラス名と同じ名前の関数を作るとコンストラクタとなり、Humanクラスをインスタンス化した時に呼び出されます。

var human : Human = new Human(“masasi”, 18);

等とHumanクラスのインスタンス化をする時にコンストラクタが呼ばれます。
クラス内にHuman関数が引数なしと引数ありの二つありますが、インスタンスを作成する時の引数の型と数によって、自動的に呼び出す関数が決定されます。(オーバーロード機能)

privateで宣言した変数にはHumanクラスからしかアクセスが出来ない為SetterとGetter関数を用いて変数にアクセス出来るようにします。

Javaのクラス作成と違うのはメソッドの作成にfunctionという文字が必要な事と引数の並びや戻り値の指定がUnityのJavaScriptの関数と同じように作成するというところでしょうか。

これでHumanクラスが作成できました。
Humanクラスはひな形なのでインスタンス化して使用する必要があります。

クラスの継承を使う

次はクラスの継承を行う場合です。
Humanクラスを継承したSuperManクラスを作成します。

Humanクラスを継承するには

class 子クラス extends Human

とします。
これもJavaと同じですね、SuperManクラスをインスタンス化すればHumanクラスの機能を使えます。

インタフェースを作成する

次はインタフェースの作り方です。
インタフェースはクラスに必ず持たせておきたい機能を宣言しておくもので、インタフェースを継承して作成したクラスは宣言した機能を実装(実際の処理を記述)する必要があります。

例えばキャラクターは必ず攻撃が出来るとしたら、インタフェースにAttackメソッドを宣言しておき、キャラクタークラスではAttackの機能を記述しなければいけないという事になります。

それではインタフェースを作成してみます。

これもJavaと同じですね、interfaceという文字の後にファイル名と同じ名前を指定します。
Attack()の後は{}(中括弧)ではなく;(セミコロン)です。

インタフェースでは実装ではなく、これがなければダメだよと宣言するだけです。
つまりインタフェースを使ったクラス(そのクラスの継承先でもよい)ではAttackの中身が記述されていないといけません。

クラスの継承とインタフェースの実装を確認してみる

それではクラスとインタフェースが出来たのでこれらを使ってみます。

シーンになんでもいいのでゲームオブジェクトを設置し、そこにMakeInstanceという新しいスクリプトを作り設置します。

Unityの実行ボタンを押して確認してみてください。

クラス1

human1.Attack()ではSuperManAttack
human2.SuperManFunction()ではSuperManFunction

という表示がされています。

SuperManのインスタンスを作成した後にSuperMan型の変数に代入した場合は、SuperManクラスで定義された機能が呼び出されます。
SuperManクラスで定義されていなければHumanクラスで探します。

SuperManインスタンスをHuman型の変数に代入した場合は
SuperMan、Humanクラス両方で定義されているメソッドであればSuperManクラスのメソッドが呼び出されます。

SuperManクラスでしか定義されていないSuperManFunctionはHuman型変数に代入したSuperManインスタンスからは呼び出せません。
SuperManクラスのSuperManFunctionを呼び出したければasを使用しキャストしてからなら呼び出せます。

ここら辺はJavaのクラスの継承と同じですね。

ではさきほど作ったインタフェースを使ってみます。

クラス名の後にimplementsと書きその後インタフェース名を記述します。
InterfaceTestインタフェースではAttackメソッドが必ず定義されていなければいけません。

Humanクラスでは元々定義していたので、インタフェースのAttackメソッドは実装されている事になります。

でも、Attackメソッドを実装してなくてもコンパイルが通っているっぽいが・・・・謎
Warningは出てるみたいですけどね。

あとはJavaScriptだと抽象クラス、抽象メソッドが作れない・・・C#だと作れるみたいなんだけど、うーむ・・・

イベントのインタフェースの実装

ではインタフェースをもっと実践的に使ってみましょう。
今まではUIのイベント処理でEvent Triggerというコンポーネントを使いイベントの発生を管理し、自前の関数を呼び出して処理を実行していました。

UnityのUIのクリックやドラッグのイベントを受け取る
UnityのUIのクリックやドラッグのイベントをEvent Triggerコンポーネントを取りつけて受け取れるようにします

↑の記事ではEvent Triggerを使っています。

しかし、Event Triggerを使わなくてもインタフェースの実装が出来るようになったので
(わたくしはやり方がわからなかったのでEvent Triggerを使っていた)

そちらを使ってボタンイベントを処理してみましょう。

クラス2

上のようにUI→Canvasを作りその子要素にUI→Buttonを作成します。
Buttonに新しくPointerDownJSという新しいスクリプトを作成し設置します。

JavaScriptで作成している時は気にする必要はありませんでしたが、MonoBehaviourクラスは必ず継承されていました。
JavaScriptでインタフェースの実装をする時は明示的にMonoBehaviourを継承しないとエラーが出る(コンポーネント追加が出来ない?)ので記述してください。

このクラスはIPointerDownHandlerインタフェースを実装します。
JavaScriptの場合はこのインタフェースがある親の階層EventSystemsから記述する必要があります。

import EventSystems;

という文言をクラス宣言の前に記述しておくと

EventSystems.IPointerDownHandler → IPointerDownHandler

に短縮して記述する事が出来ます。

C#は

using EventSystems;

です。

IPointerDownHandlerを使うとOnPointerDownメソッドを実装する必要があります。

ではUnityの実行ボタンを押して確認してみましょう。

ButtonにはEvent Triggerを取りつけていませんが、Buttonを押すたびにtestがConsoleに表示されるのが確認出来ます。

スクリプトでイベントを受け取れるようになるので、Event Triggerを取りつける必要もなくなり、イベント発生と受け取りを両方作る必要がないので少し楽になりますね。

UnityのJavaScriptを使っていてクラスを使いたい時に、
アニメーターのBehaviourを使う時はC#でしか作れず、JavaScriptのスクリプトの取得をする場合特殊な作業が必要みたいなので、C#で作っていった方が便利だなぁ・・・と思います。

今更って感じではありますがね・・・・(^_^;)