Blenderで作成した建築3DモデルをPlayCanvasでバーチャル体験してみよう

**[更新]2023/03/31に記事内の情報を大幅にアップデートしています。**

# はじめに
この「建築不動産xPlayCanvas！仮想万博作りたい人向けハンズオン」は、
2020年7月1日～(作品提出締切同年5月31日)から開催された [**仮想万博**](https://virtualexpo.matsumototd.com/) にPlayCanvasのシーンをアップするために必要な手順を説明していきます。

 - **■PlayCanvasとは**
    - PlayCanvasで実行するメリット
 - **■Blenderでの設定**
     - 3Dモデルの構造(動くオブジェクトと固定オブジェクトで分ける)
     - マテリアル設定
     - FBXのエクスポート設定
 - **■PlayCanvasプロジェクトのフォーク**
     - プロジェクトのフォーク
     - PlayCanvasエディターの説明
 - **■PlayCanvasで3Dmodel設定**
     - FBXのデータインポート
     - ビューポートへ表示
     - MeshColliderの設定
 - **■コード説明**
     - 自動ドアの開閉アニメーション
         - 扉の開くアニメーションを追加する
         - ドアを開閉するスクリプトを追加
     - 追加したスクリプトについて
 - **■PlayCanvasのアニメーションについて**
 - **■作成したプロジェクトを公開する**
     - プロジェクトのパブリッシュ

**※PlayCanvasのアカウントが作成済みであるという前提で行います。**


# ■PlayCanvasとは

JavaScriptsで作られたHTML5/WebGLで動作するゲームエンジンです。そのため、HTML5/WebGL向けコンテンツが簡単に作れます。

インストールの必要もなく、開発から公開までWebブラウザ一つで動くクラウドにホストされるため、URLにWebブラウザからアクセスすることで複数人で開発、公開したコンテンツを一緒に遊ぶことも可能です。

3Dゲームやアニメーションのほか自動車コンフィギュレーター、建築CADビューワー、オンライン展示会など幅広い業界にも活躍を見せています。

https://playcanvasjp/

## PlayCanvasで実行するメリット

PlayCanvasにインポートすることで、作成した建築モデルをWeb上で3Dビジュアライゼーションが可能になります。
これにより、建築物の外観や内部の構造をWebからいつでもで確認できるため、毎回ビルドすると言う手間もなく活用することができます。

プロジェクトを一つ作成すれば、プロジェクトを複製して他建築モデルに差し替えることもできます。
プロジェクトを再利用することで作業効率が向上し、プロジェクトのコストを抑えられます。

今回のハンズオンでは、インポートした3Dモデルの建築を一人称視点でバーチャル体験することができるものになっています。



# ■Blenderでの設定

## 3Dモデルの構造(動くオブジェクトと固定オブジェクトで分ける)

今回は必要最低限の要素にまとめます。
![blender01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341892/79413484-bd13-bcda-9fb4-409c8525b9ce.png)

メッシュ単位でマテリアルを設定し、動くオブジェクト、動かないオブジェクトで結合します。
![blender05_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341892/028b9472-9d68-e75a-6174-6a814aaf1fb1.png)

なるべくオブジェクトはまとめた方がドローコール数の削減になり表示速度がスムーズになります。
この時、オブジェクトの原点は ワールド位置[0, 0, 0]、 回転[0, 0, 0]、 スケール[0, 0, 0] にしてください。


## マテリアル設定

今回はUV展開は行わず、メッシュに基本的なカラーとスペキュラーを設定しています。
Blederの場合はプリンシパルBSDFを使用します。PlayCanvasは各3Dソフトのデフォルトマテリアルの設定を引き継げます。

建築物のモデリングではソフトシェーディングを適用した場合、エッジをはっきり見せたい部分にベベル処理やエッジ追加を行います。
モデリング、マテリアルの設定が完了したら、FBXのエクスポートを行いましょう。


## FBXのエクスポート設定

エクスポート設定は下記のように設定してください。
![blender07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341892/55dbd1c4-64f0-f568-53a7-eff421d9eed8.png)
※FBX変更後にテクスチャやfbxのパスを変更しない(テクスチャのリンクが切れるため)


# ■PlayCanvasプロジェクトのフォーク

こちらのURLのプロジェクトをフォーク(複製)します。
https://playcanvas.com/project/669054/

このプロジェクトは、一人称視点＆キャラクターコントロールがセットされているプロジェクトです。

## プロジェクトのフォーク

フォークボタンをクリックし、任意のプロジェクト名を入力後、enterキーもしくはforkボタンをクリック
![playCanvas01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341892/e4553aac-a750-2b5f-4f1e-f9dd81b9f036.png)
![playCanvas03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341892/62f02296-5323-ad1c-ffcd-e628064bec15.png)

複製されたプロジェクトが開きます。
 **EDITOR** ボタンをクリックすると、PlayCanvasのビジュアルエディターが開きます。
![playCanvas04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341892/ac581390-9935-6297-96f9-945cd28e064e.png)

SCENES選択画面の **Untitled** をクリックします。
![playCanvas05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341892/081a4691-246f-d5de-3b2a-f5e26b8d267a.png)


## PlayCanvasエディターの説明

PlayCanvasはスクリプト作成以外の作業をこのEditorから操作することができます。
Editorの構成は以下のようになっています。
![editor.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341892/50a06d9f-86ae-5971-ae34-d493e01a88ad.png)
各要素は以下のとおりです。

 1. **シーン(SCENE)**
シーンビューには、制作しているのシーンが表示され、自由な位置・角度から眺めることができます。

 2. **インスペクター(INSPECTOR)**
シーンの中で選択中のオブジェクトのプロパティなどを表示・編集するためのビューです。
座標やメッシュといった見た目上のものから、衝突判定や物理制御に関するパラメーターなどもあり、ユーザーが定義する要素がここに表示されます。

 3. **ヒエラルキー(HIERARCHY)**
シーン内に存在するオブジェクトの一覧が表示されます。
編集中のシーン内でオブジェクトをコピー/ペーストしたり、適切な名前をつけて整理することもできます。

 4. **アセット(ASSETS)**
制作中のプロジェクト（ゲーム全体）に含まれるモデル、スクリプト、グラフィックやサウンドなどのデータ、その他のリソースがファイル単位で表示されます。

 5. **メニュー(MENU)**
シーンのビューモードやプロジェクトセッティング等の作業が行えます。



# ■PlayCanvasで3Dmodel設定

プロジェクトのHIERARCHYを見ると **Level** という室内モデルが既に入っています。
![playCanvas06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341892/11f0f9d7-432f-240f-ddaf-739bf98f04f5.png)

右上の **Launch** ボタンをクリックし、実行画面を確認してみましょう。
![playCanvas07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341892/21adb3f7-a8ef-861e-6d62-1afc45176660.png)

**W,A,S,Dキー**で移動、**スペースキー**でジャンプします。

## FBXのデータインポート

PlayCanvasのASSETS欄に新規で **BuildingModel** とい言う名前でフォルダを作成します。
![playCanvas10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341892/6ebad596-1c0d-1a38-b09b-d3429f0c72f7.png)
![playCanvas11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341892/8ec3200c-7408-a37f-4de7-1ac9781a4e22.png)

BuildingModelを選択した状態で、**＋ボタン** の Add Assets から Upload で、データをインポートもしくはローカルフォルダからドラック＆ドロップでASSETSにインポートします。
![playCanvas12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341892/d42c7585-013b-691a-74a0-2f1bf20e5436.png)
![playCanvas13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341892/881d9cd9-9bf9-b692-4d2e-848732bee867.png)
![playCanvas14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341892/15ca5c57-15ef-be6b-2932-b984f3708f79.png)
FBXのマテリアル設定が正しく行えていると、カラーやスペキュラー強度が引き継がれた状態でマテリアルが展開されます。
また、FBXは自動でJavaScriotが解読可能なJSON形式へ自動変換されます。FBX自体は使用しないので削除しても構いません。


## ビューポートへ表示
**Level** と **Camera** モデルは制作の邪魔になるため、削除もしくは **Enabled** のチェックをFalseに外してください。
![playCanvas09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341892/7c62571d-e608-5267-5cb9-b79ea020d792.png)

ASSETS内の〇〇〇.jsonをシーンビューへドラック＆ドロップしてください。
![playCanvas15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341892/f4bf5bb7-f081-b384-18f8-2ad3816411a6.png)

3Dソフト上で設定した原点情報を元に表示されますので、例えばオブジェクトの原点がオブジェクトを中心に設定されてる場合、PlayCanvasのシーンビュー上の中心(位置0,0,0)に表示されます。
![playCanvas16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341892/59f2a18c-4a22-e68f-8a2b-47c7cb8c6faa.png)


各オブジェクトをシーンビューにアップしたらオブジェクト内を歩けるように設定していきます。


## MeshColliderの設定

各建物オブジェクトのINSPECTER内のADD COMPONENTから **Collision** と **Rigit Body** を選択します。
![playCanvas18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341892/38293408-e22a-64ec-ce18-47c07c19b15d.png)

COLLISIONのTypeをMeshに変更しAssetsに同じオブジェクトを選択すると、そのオブジェクトの形状のCollisionになります。
![playCanvas19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341892/29e8e5e0-0cd3-5be9-cbc0-bcdba911ecc0.png)
![playCanvas20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341892/82bf46a3-9d3a-efee-e70a-ee120e2c5ea8.png)

これで建物内を自由に移動することが出来るようになりました。
Lauchで確認してみましょう。



# ■コード説明

ここではシンプルなアニメーション制御(自動ドアの開閉)に関する説明を行います。

## 自動ドアの開閉アニメーション

ドアも **COLLISION** と **RIGID BODY** を追加します。
COLLISIONのTypeは **Mesh** 、RIGID BODYのTypeは **Kinematic** にします。
<img width="313" alt="ScreenShot 18.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257048/02276adc-a298-1304-8c4c-36f525126ff1.jpeg">


### 扉の開くアニメーションを追加する

 1. ADD COMPONENTをクリック
![](https://i.imgur.com/Z06Sl22.png)

 2.  Animationを選択
![](https://i.imgur.com/EJLRtrZ.png)

 3. Add Assetsをクリック
![](https://i.imgur.com/EB52LRo.png)

 4. アニメーションを選択し。ADD SELECTIONをクリック
![](https://i.imgur.com/cynTrQ0.png)

 5. DONEをクリック
![](https://i.imgur.com/clIwvid.png)

 6. Activate・Loopのチェックを外します。
![](https://i.imgur.com/88sa7sL.png)


### ドアを開閉するスクリプトを追加

 1. ADD COMPONENTからScriptコンポーネントを追加します。
![](https://i.imgur.com/wTlAwBl.png)

 2. ADD SCRIPTをクリックし、`door`というスクリプトを追加します。
![](https://i.imgur.com/yC8EPVA.png)

 3. Select Entityをクリックします。
![](https://i.imgur.com/5e8yqok.png)

 4. PlayerのEntityをクリックします。
![](https://i.imgur.com/P4UHaVW.png)

これで自動ドアを作成するためにスクリプト・アニメーションの設定は完了です。


## 追加したスクリプトについて

このスクリプトは、ドアに、属性で指定をしたエンティティが触れたらドアを3秒開けるというスクリプトになります。


今回使用した主な処理は以下の通りです。

 1. イベントハンドラーについて
https://developer.playcanvas.com/en/api/pc.EventHandler.html

 2. AnimationComponent
https://developer.playcanvas.com/en/api/pc.AnimationComponent.html

 3. CollisionComponent
https://developer.playcanvas.com/en/api/pc.CollisionComponent.html

 4. RigidBodyComponent
https://developer.playcanvas.com/en/api/pc.RigidBodyComponent.html

```javascript
 /*jshint esversion: 6, asi: true, laxbreak: true*/
const Door = pc.createScript('door');
Door.attributes.add("player", { type: "entity" })

Door.prototype.initialize = function () {
    const ANIMATION_NAME = "open" // ※アニメーション名を指定
    const animation = this.entity.animation.getAnimation(ANIMATION_NAME)
    const duration = animation.duration
    this.rayEnd = {x:1, y:1, z:1}
    this.isOpen = false
    this.timer = 0
    
    this.entity.on(`door:open`, () => {
        this.entity.rigidbody.enabled = false
        this.entity.animation.speed = 0.5
        this.entity.animation.play(ANIMATION_NAME)
        this.isOpen = true 

    })
    
    this.app.on(`door:close`, () => {
        const result = this.app.systems.rigidbody.raycastFirst(this.entity.getPosition(), this.rayEnd)
        if(result !== null){
            this.timer = 0
            return
        }
        this.entity.rigidbody.enabled = true
        this.entity.animation.speed = -0.5
        this.entity.animation.play(ANIMATION_NAME, duration)
        this.isOpen = false
    })
    
    this.entity.collision.on("collisionstart", (e) => {
        const { other } = e
        if (other.name === this.player.name && !this.isOpen) {
            this.entity.fire(`door:open`)
        }
    })
};

Door.prototype.update = function(deltaTime){
   if(!this.isOpen) return
   this.timer += deltaTime 
   if (!this.entity.animation.playing && this.entity.animation.duration +  this.timer > 3) {
        this.app.fire(`door:close`)
        this.timer = 0
    }
}
```



# ■PlayCanvasのアニメーションについて

PlayCanvasのアニメーションに制御ついては、こちらの記事にアニメーションの制御について書いた記事がありますのでそちらをご参照ください。
[【PlayCanvas】スクリプトによるアニメーション制御 ・順再生・逆再生・ループ
](https://qiita.com/yushimatenjin/items/8a426a9aed9f4996b70d)



# ■作成したプロジェクトを公開する
完成したプロジェクトをパブリッシュして、みんながプレイできるURLを生成します。


## プロジェクトのパブリッシュ

左のメニュー、またはシーンの左上の **Manage Scenes** から以下のPublish画面を開きます。

![playCanvas29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341892/0dc1f5e2-9911-9070-347a-63dff2050a64.png)
![playCanvas26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341892/af5f2170-7c6a-1002-7342-c9c2ad2332dd.png)

**PUBLISH TO PLAYCANVAS** を選択して、一番下の **PUBLISH NOW** をクリックしてビルドは完了です。
![playCanvas27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341892/14d057b5-7fb9-239d-5d82-0a95bdf38169.png)

発行された実行URLには、PC・スマホ・VRデバイスのWebブラウザがあれば、PlayCanvasにログインする必要もなくコンテンツを共有することができます。

以上で完了です。
お疲れさまでした。