PlayCanvasでサンディちゃんを歩かせるゲームを作るぞ☆（第6回）~他エンティティのイベントを拾う~

# こんなん作ってます。
https://playcanv.as/b/iAPwWXqY/
※本解説よりも開発が進んでいることもございますのでご了承ください。

# 一つのエンティティの衝突判定をUI用のエンティティに伝えるにはどうする？
例えばゴールポスト的な赤い円柱があって
![スクリーンショット 2020-02-24 1.10.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110583/1cea3cb0-4a7b-eb76-0ad7-7c343bdcac94.png)

これに触れるとダイアログがでる。
![スクリーンショット 2020-02-24 1.10.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110583/fa9c7c80-8381-71eb-8575-2f51cc56f0b4.png)


PlayCanvasは各エンティティにスクリプトを持たせてプログラミングされますが、円柱とUIは違うエンティティです。

どうやってエンティティ間でやりとりをしたらよいのでしょうか？

答えはユーザマニュアル>スクリプティング>通信にありました。
https://developer.playcanvas.com/ja/user-manual/scripting/communication/

通信ってのはなかなか聞かない表現かもしれませんが、他のエンティティのイベントを拾ってくることだと考えてください。

スクリプト間の通信には

- スクリプト属性で参照づけられているエンティティのみから拾ってくるイベント
- メインアプリケーション(this.app)を中央ハブとして、全てのエンティティから拾ってこれるアプリケーションイベント

の２種類があります。
どうみても後者が便利です（笑）

エンティティにサンディちゃんが衝突した際にUI部品へ衝突判定を伝えるよう、アプリケーションイベントを使ってプログラミングしていきます。


# 衝突判定
以下のスクリプトを作成します。

```hitSandy.js
var HitSandy = pc.createScript('hitSandy');

// initialize code called once per entity
HitSandy.prototype.initialize = function() {
    this.entity.collision.on('triggerenter', this.onTriggerEnter, this);
};

// update code called every frame
HitSandy.prototype.update = function(dt) {
    
};

HitSandy.prototype.onTriggerEnter = function(entity) {
    this.app.fire('hitSandy:hit', this.entity.name, entity.name);
};
```

このスクリプトが適用されているエンティティの当たり判定に、何かしら剛体が衝突した際に「hitSandy:hit」というイベントを発火するようにしました。

ちなみに「hitSandy:hit」イベントを受け取った側は衝突した２つのエンティティの名前を受け取ることができます。

このスクリプトを[PlayCanvasでサンディちゃんを歩かせるゲームを作るぞ☆（第4回）](https://qiita.com/bcosizm/items/b4c11aed23a5d42e25c6)で作成したtemplatesディレクトリ内の「start」「goal」エンティティに適用してください。

（例）
![スクリーンショット 2020-02-24 1.39.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110583/f6d02786-6cd5-96ce-45b4-d1777032fc4c.png)


# 衝突判定をUIで表示する
イベントの通知を受け取るスクリプトの初期化関数でイベントの受け取りと、イベントを受けたときのイベントハンドラを作成。
今回の場合、当たり判定の衝突を検知したら「onSandyHit」関数をコールする。
衝突イベントからは衝突した２つのエンティティの名前も届いて、「onSandyHit」関数ではname1,name2の引数がそれを受け取るようになっています。

```ui.js
// initialize code called once per entity
Ui.prototype.initialize = function() {
・・・
    // initializeメソッドに以下を追加
    // listen for the player:move event
    this.app.on('hitSandy:hit', this.onSandyHit);

    // remove player:move event listeners when script destroyed
    this.on('destroy', function() {
        this.app.off('hitSandy:hit', this,onSandyHit);
    });
}

//onSandyHitメソッドを新規追加
Ui.prototype.onSandyHit = function(name1,name2) {
    // 第1引数は衝突された側のエンティティの名前、第２引数は衝突したエンティティの名前
    // メッセージを作成。
    var caption = "";
    var message = "";
    if(name1=="start"){
        caption = "START";
        message = name2 + " start!!";
    }else if(name1 == "goal"){
        caption = "GOAL";
        message = name2 + " reach the goal!!";
    }

    // ダイアログにメッセージを載せる
    var disp_dialog = document.getElementsByClassName('pos_top_center')[0];
    disp_dialog.style.display = "block";
    disp_dialog.getElementsByClassName('caption')[0].innerHTML = caption;
    disp_dialog.getElementsByClassName('message')[0].innerHTML = message;

};
```

これでLaunchしてみましょう。

START
![スクリーンショット 2020-02-24 16.26.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110583/e7ee2b75-2586-0630-f39b-8018e6ecff5c.png)

GOAL
![スクリーンショット 2020-02-24 16.27.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110583/13f2378e-56c4-5a10-9a3b-d2246f71ead9.png)