PlayCanvasで作成したゲームをPWAにしてAndroid端末へインストールする

### PlayCanvasで作成したプログラムをPWAにしてリソースをキャッシュする

はがです。

PWAアドベントカレンダーの記事となります


####

今回のデモはこちらになります。

コインドーザー
[https://yushimatenjin.github.io/](https://yushimatenjin.github.io/)



#### PlayCanvasからダウンロードします

まずPlayCanvasで作成したプロジェクトをダウンロードします。
![](https://i.imgur.com/PAnD0uL.png)


#### ダウンロードされたファイルについて

PlayCanvasからダウンロードされたファイルは、`index.html`を始めとする静的なファイルが入っているものになります。

![](https://i.imgur.com/fQR4tHn.png)



#### PWA対応のウェブサイトを作る

PlayCanvasで作ったゲームをPWAに対応させるために２つのファイルを追加します。

- serviceWorker.js
- manifest.json

manifest.jsonはゲームの基本的な情報を記載します

```manifest.json
{
  "name": "コインドーザー",
  "short_name": "コインドーザー",
  "icons": [
    {
      "src": "https://yushimatenjin.github.io/logo192.png",
      "sizes": "192x192",
      "type": "image/png"
    }
  ],
  "start_url": "https://yushimatenjin.github.io/",
  "display": "standalone",
  "background_color": "#f16625",
  "theme_color": "#f16625"
}
```

https://yushimatenjin.github.io/manifest.json

serviceWorker.jsにはキャッシュについてを記述します。




https://yushimatenjin.github.io/serviceWorker.js

```serviceWorker.js

    var CACHE_NAME = 'coin-dozer-version-1';
    var urlsToCache = [
    キャッシュするファイル....
    ];
    
    self.addEventListener("install", function(event) {
      event.waitUntil(
        caches.open(CACHE_NAME).then(function(cache) {
          return cache.addAll(urlsToCache);
        })
      );
    });
    
    self.addEventListener("fetch", function(event) {
      event.respondWith(
        caches.match(event.request, {
			ignoreSearch: true
		}).then(function(response) {
          if (response) {
            return response;
          }
          return fetch(event.request);
        })
      );
    });
    

```

### serviceWorker.jsを一瞬で作る

`playcanvas-tools`というnpmのパッケージを作りましたのでこちらを使用すると、１つのコマンドでserviceWorker.jsを作ることができます。

ソース
https://github.com/yushimatenjin/playcanvas-cli


npm

https://www.npmjs.com/package/playcanvas-tools


### npx

```
cd PlayCanvasのプロジェクトを解凍したフォルダ
npx playcanvas-tools sw --name キャッシュ名
```

#### PlayCanvas特有の問題

PlayCanvasはロードするたびにクエリーストリングを追加します。そのURLについてもキャッシュを適用させるために`caches.match`無視するオプションを追加します。

https://developer.mozilla.org/en-US/docs/Web/API/Cache/match

```serviceWorker.js
caches.match(event.request, {
        ignoreSearch: true
})
```


```serviceWorker.js
self.addEventListener("fetch", function(event) {
  event.respondWith(
    caches.match(event.request, {
        ignoreSearch: true
    }).then(function(response) {
      if (response) {
        return response;
      }
      return fetch(event.request);
    })
  );
});
```


このオプションを追加することでキャッシュから呼び出されるようになります。

![](https://i.imgur.com/kFBaIuP.png)



#### index.htmlからServiceWorkerを読み込むコードを追記する

index.htmlのHead内にこちらのコードを追加します。

```index.html
<script>
    if ("serviceWorker" in navigator) {
      navigator.serviceWorker
        .register("./serviceWorker.js")
        .then(function(registration) {
          if (typeof registration.update == "function") {
            registration.update();
          }
        })
        .catch(function(error) {
          console.log("Error Log: " + error);
        });
    }
  </script>
```

https://github.com/yushimatenjin/yushimatenjin.github.io






## キャッシュ無し
![](https://i.imgur.com/L7YAoTd.jpg)

![](https://i.imgur.com/iKAf7V9.png)

## キャッシュ有り
![](https://i.imgur.com/TZ72nUq.jpg)

![](https://i.imgur.com/ARXXnJS.png)


キャッシュをしないと28.1MBのダウンロードをしていたファイルをキャッシュすることで、２回目以降の読み込みを24.2KBまでにすることにできます。



## インストールが可能になる

さらに下記の要件を満たすことでAndroidの端末へインストールすることができます。

1. manifest.jsonに必要な要件を入れる
   - short_nameかname
   - icons 192pxか512px
   - start_url
   - display,fullscreen,standalone,minimal-uiのうちどれか
2. HTTPSの設定
3. fetchイベントハンドラをserviceWokerに追加する

#### Androidの表示
![](https://i.imgur.com/SsSIs73.jpg)


#### iOSの表示
![](https://i.imgur.com/PcAOYXJ.jpg)


## Storeにも出せる
TWAと言われる形でビルドをすることでストアに出すこともできました。
![](https://i.imgur.com/R0kJ5OJ.png)



<font color="OrangeRed">
PlayCanvas開発で参考になりそうな記事の一覧です。
</font>
<font color="OrangeRed">
入門

- [PlayCanvas入門- モデルの作成～ゲームに入れ込むまで](https://qiita.com/yushimatenjin/items/2a2c35fe7b1d08f9e361)
- [JavaScriptでスロットを実装する。【PlayCanvas】](https://qiita.com/yushimatenjin/items/e84c42da74df1eb07386)
- [3Dモデルのビューワーを3分で作る【初めてのPlayCanvas】](https://qiita.com/yushimatenjin/items/4b09c9e2076a0b2a6933)
</font>
<font color="OrangeRed">
応用
</font>

- [PlayCanvasのコードエディターでes6に対応する](https://qiita.com/yushimatenjin/items/a61a21c64c1c1a550dd4)
- [Gulpのプラグインを書いたらPlayCanvasでの開発がめちゃくちゃ便利になった](https://qiita.com/yushimatenjin/items/5f0f178e8a4ba4a5ee57)
- [PlayCanvas Editorに外部スクリプトを読み込む新機能が追加されたので開発方法を考える。- Reduxを組み込む](https://qiita.com/yushimatenjin/items/7a64220cceac66843d7d)
</font>
<font color="OrangeRed">
その他の記事はこちらになります。

- [React Native + PlayCanvasを使ってスマートフォンゲームを爆速で生み出す](https://qiita.com/yushimatenjin/items/7c7ad5d35473c11f32f2)
- [PlayCanvasのエディター上でHTML, CSSを組み込む方法](https://qiita.com/yushimatenjin/items/814b4a32db53397219df)
- [【iOS13】新しくなったWebVRの使い方 ](https://qiita.com/yushimatenjin/items/344d86b3d193e0a88567)
</font>

<font color="OrangeRed">
その他関連
- [PlayCanvasタグの付いた記事一覧](https://qiita.com/tags/playcanvas)
</font>


### PlayCanvasのユーザー会のSlackを作りました！
少しでも興味がありましたら、ユーザー同士で解決・PlayCanvasを推進するためのSlackを作りましたので、もしよろしければご参加ください！

[日本PlayCanvasユーザー会 - Slack](https://t.co/IdSRIfJhN5?amp=1)