以前のバージョンと比較しながら3DサポートされたProject Tinyを触ってみる

この記事は[PONOS Advent Calendar 2019](https://qiita.com/advent-calendar/2019/ponos)の21日目の記事です。


#はじめに
本記事では、Project Tinyを以前のバージョンと比較しながら、
先日リリースされた3Dサポートバージョン（0.20.0-preview.3）の導入方法や使用感について
紹介していきます。


#Project Tinyについて
コアランタイムサイズが極めて小さい、Unityの軽量版です。
用途としては、モバイルブラウザ向けゲームや
プレイアブル広告（広告内でゲーム等がプレイ可能な広告）を作成するための機能
として提供されています。
https://blogs.unity3d.com/jp/2018/12/05/project-tiny-preview-package-is-here/

以前はPackage Managerに**Tiny Mode**と表記されていましたが、
最新のバージョン(0.20.0-preview.3)では**<font color="Red">Project Tiny</font>**の表記に変更されていました。


#バージョンごとの大きな変更点
変更ログ
https://docs.unity3d.com/Packages/com.unity.tiny@0.16/changelog/CHANGELOG.html

## <font color="Red">**ver0.13.2-preview**</font>
- 2018年12月4日から公開
- オープンβとしてPackageManagerに公開
- **Unity2018.3.0b12以降**から使用可能
- 専用の**Tiny Mode**と呼ばれるモードで構築
- **ECS**ベースで作成
- スクリプトは**TypeScript**のみ


### 導入・作成方法
*詳しい導入方法は紹介しませんが、htmlファイルを出力するまでの流れを紹介します。*

1. Tiny ModeとしてPackageManagerからインストール
2. **Editor上のTinyタブ**からTiny Mode用のプロジェクトを作成
3. Hierarchyから**EntityGroup**（シーンのようなもの）を作成、その中に**Entity**を作成
4. 必要に応じて**TypeScript**を作成し、Entityを制御

#### 実行
Editorから実行するとローカルサーバーが立ち上がり、ブラウザ上で表示されます。
GameViewではQRコードが表示されているため、モバイルからの確認も可能です。
対応している出力形式は**HTML5**のみです。

#### ビルド
**.utproject**ファイルを選択してReleaseモードでBuildすることでhtmlファイルが出力されます。
ただし、表示するにはhtmlファイルをサーバーに配置する必要があります。
**htmlファイルの出力先： [ProjectName]/⁨TinyExport⁩/[TinyProjectName]⁩/⁨html5⁩/release⁩/⁨bin⁩**

![スクリーンショット 2019-12-18 14.10.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537483/0aa55c91-dc27-7632-f0c9-b35eab3b9d90.png)

### 使用感
- 今後C#が対応されるため、現状のTypeScriptから自動移行できる機能がないのであれば、  
  スクリプトによる実装は様子見のほうがよいと思われます
- 実行から確認までの時間は早く、GameViewにQRコードも表示されるため、  
  本来の目的であるモバイルでの実装確認も容易に行える
- 出力されたhtmlファイルからの実行も、ブラウザで読み込みまでの時間もほんの数秒でした
- また、releaseビルドでSprite一枚のみを配置したバイナリのサイズは**2MB**でした


## <font color="Red">**ver0.15.3-preview**</font>
- 2019年5月31日から公開
- **Unity2019.2.0b3以降**から使用可能
- <font color="Red">以前のバージョンとの互換性はなし</font>
- **TypeScriptのサポート廃止**
- **C#対応**
- QRコード削除
- DOTS APIサポート
- **DOTS mode**の追加
- プロジェクトファイルの拡張子が.utprojectから.projectファイルに変更
- 一部Tinyの表記がDOTSに変更


### 導入・作成方法
*詳しい導入方法は紹介しませんが、htmlファイルを出力するまでの流れを紹介します。*

1. Project TinyとしてPackageManagerからインストール
2. エラーが出るので、PackageManagerから**Burst（バーストコンパイラ）を1.1.2にアップデート**
3. <font color="Red">DOTSモードに正常に移行しない場合があるので一度Unityを再起動</font>
4. **Editor上のDOTSタブ**からTiny Projectを作成
5. Hierarchyからシーンを作成し、シーン内にEntityを作成

#### 実行・ビルド
選択したPlatformに合わせた形式で実行およびビルドされます。
実行時にビルドも合わせて行われるためhtmlファイルも出力されます。
**htmlファイル出力先： [ProjectName]⁨/⁨Library⁩/DotsRuntimeBuild/⁨build⁩/[ProjectTinyName]/[ProjectTinyName]-[platform]-[buildtype]**
ただし、表示するにはhtmlファイルをサーバーに配置する必要があります。

対応しているプラットフォームは、Mac、WindowsとWebです。

![スクリーンショット 2019-12-18 16.53.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537483/41bfdfc1-91a3-615b-7e15-1b86d275fad7.png)

![スクリーンショット 2019-12-18 16.53.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537483/c473f56a-d9be-e7c3-8b7f-e3917e3c2d56.png)


### 使用感
- PackageManagerからインストール後にコンソール上にエラーが表示されたりと導入時点から躓いてしまいました
forumに改善方法が載っていたため参考にしながら導入を進めることをおすすめします  
https://forum.unity.com/threads/project-tiny-preview-0-16-1-c-available-and-upcoming-changes.708875/
- ver0.13.2と同様に専用のEditorモードでの作成になりますが、多少、名称等は変わりましたが機能自体は然程変わっていなかったです
- 実行の際に合わせてビルドを行うため、初回は時間がかかりますが二回目以降は数秒で確認ができます。 
できれば実行とビルドは分けて、Editor上で確認できるのが理想なところです
- C#対応後でも高速に起動・読み込み
- releaseビルドでSprite一枚のみを配置したバイナリのサイズは**1.7MB**

## <font color="Red">**ver0.20.0-preview.3**</font>
3Dサポートリリース！
https://forum.unity.com/threads/project-tiny-fall-update-tiny-racing-preview-3-020-0-is-available.792999/

- 2019年12月12日から公開
- **Unity2019.3.0f1以降**から使用可能
- **<font color="Red">3Dサポート</font>**
- **iOS/Android/HTML5/Windows/Mac**のビルドサポート
- 以前のバージョンからの移行は手動で行う必要があり
- 独自のエディターモード(DOTS mode）を廃止
- DOTS変換のワークフローを採用
- 2D、UI、物理演算、アニメーション等の機能はまだ含まれていない（2D、物理演算は2020年にサポート予定）
- 今後は既存のUnityに依存しないように提供していくことを目標

### デモ
Unity公式から公開されているデモ
http://www.tiny.vision/TinyRacing/TinyRacing.html


# 3Dサポートされたver0.20.0-preview.3を触ってみる
**forumにあるドキュメントを参考に導入をしていきます。**
https://docs.google.com/document/d/1A8hen2hLFY5FLkC5gd3JP2Z-IpHfnAX-CpYLK3aOdwA/edit#

## 環境
- Unity 2019.3.0f3
- Project Tiny 0.20.0-preview.3

## 導入方法

#### Packages/manifest.jsonに以下を定義

```
"com.unity.dots.runtime": "0.1.0-preview.5",
"com.unity.tiny": "0.20.0-preview.3",
"com.unity.tiny.desktop": "0.20.0-preview.2",
"com.unity.tiny.rendering": "0.20.0-preview.3",
"com.unity.tiny.web": "0.20.0-preview.2",
"com.unity.platforms": "0.1.7-preview.3",
"com.unity.platforms.android": "0.1.7-preview.6",
"com.unity.platforms.desktop": "0.1.7-preview.2",
"com.unity.platforms.ios": "0.1.7-preview.10",
"com.unity.platforms.linux": "0.1.7-preview.3",
"com.unity.platforms.macos": "0.1.7-preview.3",
"com.unity.platforms.web": "0.1.7-preview.6",
"com.unity.platforms.windows": "0.1.7-preview.4",
```  
　
#### PackageManagerからHybrid Rendererをインストール
DOTSに変換したオブジェクトを描画するために、インストールします。
バージョンは**<font color="Red">"0.3.0-preview.4"</font>**
最新のバージョンではエラーが出て駄目でした。
![スクリーンショット 2019-12-18 18.53.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537483/e2728baa-2617-971e-86d0-a13f2e77c22c.png)

　
#### Assembly DefinitionにProject Tinyを定義

Assetsを右クリックして、**Create**→**Assembly Definition**を選択
<img width="563" alt="スクリーンショット 2019-12-19 1.02.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537483/a59f7ee0-42ef-c5a2-dfe1-a81633d6ee91.png">

名前はProjectNameにしておきます。
<img width="238" alt="スクリーンショット 2019-12-19 1.02.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537483/5451cb6d-00be-cb43-0fcd-04e3491d59bc.png">

作成したAssemblyDefitionファイルを選択し、
**Auto Referenced**と**Use GUIDs**のチェックを外します。
<img width="260" alt="スクリーンショット 2019-12-19 1.05.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537483/83cc54c2-c91a-1249-5cd2-541635420d2c.png">

次に、**Assembly Definition References**に以下のAssemblyファイルの
参照を付け足していきます。

```
Unity.Entities
Unity.Transforms
Unity.Mathematics
Unity.Tiny.Core
Unity.Tiny.Rendering
Unity.Tiny.EntryPoint
Unity.Tiny.Main
```
<img width="425" alt="スクリーンショット 2019-12-19 1.15.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537483/c7b4932c-601c-2c68-0b49-9eefa41b1bb1.png">

追加後、下までスクロールしてApplyを選択します。


#### Universal Renderning Pipeline（以下URP）の導入

**URP**をPackageManagerからインストールしておきます。
<img width="835" alt="スクリーンショット 2019-12-19 11.03.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537483/b6f774f3-8788-1385-6abb-08fa0b186fa4.png">

インストール後、URPを作成していきます。
Assetsを選択して、右クリックから**Create**→**Rendering**→**Universal Render Pipelilne**→
**Pipeline Asset(Forward Renderer)**を選択して作成します。
<img width="670" alt="スクリーンショット 2019-12-19 11.14.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537483/fc02b410-1168-05af-c9f8-91c100f61fef.png">

作成したURPを設定していきます。
**File**→**Build Settings**→**Player Settings**→**Graphics**を選択して、
**Scriptable Render Pipeline Settings**に先程作成したものを設定していきます。
<img width="449" alt="スクリーンショット 2019-12-19 11.16.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537483/9a251212-2f4a-7449-7a7d-1178646f27ab.png">



## 作成
**今回は、Unityで配置された3Dのキューブを回転させることを目標とします。**

そのためにこれから以下の作業を行っていきます。

- シーンを作成し、一部のオブジェクトをSubSceneとして設定
- SubSceneにCubeを配置
- 回転するためのComponentDataとComponentSystemを作成

#### シーンを作成し、一部のオブジェクトをSubSceneとして設定
SubSceneとして設定し、Entity化することで、
Project TinyのECSベースでも表現できるようにしていきます。

SubSceneについては、詳しく説明していただいているこちらをご参考ください、
http://tsubakit1.hateblo.jp/entry/2019/03/07/013558
　
シーンを新たに作成します。
**Main.unity**
<img width="239" alt="スクリーンショット 2019-12-19 1.41.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537483/b6589baa-aa66-fa0a-9b8d-4e640360e190.png">

Mainシーン内に、オブジェクトをSubSceneに設定するため、
空のオブジェクトをCreate Emptyで作成します。
<img width="249" alt="スクリーンショット 2019-12-19 1.41.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537483/9fbdd5df-6f5c-7af4-2179-d2af20379f19.png">

オブジェクトを選択した上で、
右クリックで**New SubScene From Selection**を選択すると、
SubSceneとして作成されます。
 <img width="382" alt="スクリーンショット 2019-12-19 1.41.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537483/83727f5f-0e40-0e12-d80c-d1df1be9d760.png">
<img width="443" alt="スクリーンショット 2019-12-19 1.44.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537483/4ca59095-b9c8-f6c0-b025-3192789c1665.png">


SubScene設定の際にできた、子オブジェクトは削除しておきます。
<img width="235" alt="スクリーンショット 2019-12-19 1.42.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537483/c3ad800f-e9b1-6fc2-ebae-c9c738a6ad81.png">
また、ProjectビューのSceneのディレクトリも削除して同じ階層に移動させます。
<img width="237" alt="スクリーンショット 2019-12-19 1.42.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537483/2ac131c7-455f-3483-afbc-df5e86aa864d.png">


#### SubSceneにCubeを配置
SubSceneを編集するには、Projectのシーンファイルを開いて、直接編集をするか、
MainシーンからSubScene化したオブジェクトを選択して、
SubSceneComponentからEditモードにすることでも編集が可能です。
今回はEditモードを使用します。
<img width="443" alt="スクリーンショット 2019-12-19 1.44.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537483/b465a4da-07b7-492a-5fd7-b465614379b8.png">

Editモードにした状態で、SubSceneのオブジェクト階層に、
MainCameraとDirectionl Lightを複製します。
そして、Createから3DのCubeを追加します。
<img width="244" alt="スクリーンショット 2019-12-19 1.44.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537483/b6aefd29-363a-fd31-4d52-ae3085841c2e.png">


#### 回転するためのComponentDataとComponentSystemを作成
**IComponentData**を継承したRotateComponent.cs、
**ComponentSystem**を継承したRotateSystem.csをそれぞれ作成します。

```RotateComponent.cs
using Unity.Entities;

[GenerateAuthoringComponent]
public struct RotateComponent : IComponentData
{
    public float Speed;
}
```

```RotateSystem.cs
using Unity.Entities;
using Unity.Transforms;
using Unity.Mathematics;

public class RotateSystem : ComponentSystem
{
    protected override void OnUpdate()
    {
        var dt = Time.DeltaTime;
        Entities.ForEach((ref Rotation rot, ref RotateComponent rc) => {
            rot.Value = math.mul(rot.Value, quaternion.RotateY(dt * rc.Speed));
        });
    }
}
```
　
RotateComponentを回転させるCubeに追加します。
<img width="619" alt="スクリーンショット 2019-12-19 2.37.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537483/60608a89-8f60-3fb7-d3f5-933df7e94de6.png">


## 実行
今までのTinyとは異なり、
Unity Editorから実行することで動作・表示の確認が可能です。


## ビルド
ビルドには**Build Settings for DOTS Runtime**というものを使用していきます。
Assetsを右クリックして、**Create**→**Build**→**Build Settings for DOTS Runtime**を選択。
それぞれ設定を追加していきます。

**General Settings**
Product Name → プロジェクト名を記入
Company Name　→ 会社名を記入

**Scene List**
ScenesにSizeを1を指定し、表示するシーンを追加

**Dots Runtime Build Profile**
Web向けにビルドを行うので、TargetをWeb(Wasm)に選択

右下の+ボタンより追加
**（追加）Conversion System Filter Settings**
Sizeに1を指定し、Unity.Rendernig.Hybridを指定

**（追加）Emscripten Settings**
Sizeに1を指定し、**TOTAL_MEMORY=64MB**を指定

<img width="680" alt="スクリーンショット 2019-12-19 11.22.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537483/080c9f54-5a89-8fb6-eaa8-983f9c3f4566.png">

Build And RunからWeb用のバイナリが出力されます。
**バイナリ出力先：⁨[プロジェクト名]⁩/⁨Builds⁩/DotsRTBuildSettings/**
以前のバージョンと同様に表示するにはhtmlファイルをサーバーに配置する必要があります。

## デモ
※Webブラウザで動いています
※Gifにしたことで少しカクついていますが、スムーズに動いています。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537483/db5800a1-3aa2-5e72-d026-d76526998878.gif" width="60%" height="60%">



## 使用感
- 専用のモードが廃止されたことにより、今までのUnityのように実装可能になったのは大きな点かと思います
- ただ以前のバージョンまでと比べても設定する項目が増えたため、より実装が複雑になったと感じます
- cubeを数個配置したバイナリのサイズは**2.9MB**でした

# おわりに
- Project Tinyではどのコードモジュールを含めるかを細かく制御できるため、  
ランタイムサイズが小さく、起動までの時間も短縮することが可能です
- ただ、実装にはDOTSを詳しく理解する必要があるため学習コストは高いです
- まだプレビュー版のためバージョンが上がるごとに大きな変更や  
一部の機能が廃止されたりしてしまう可能性もあります。
様子をみながら実装を進めていくことをおすすめします  
Unity forumのProject Tinyのスレッドがおすすめです  
https://forum.unity.com/forums/project-tiny.151/

明日は@nisei275さんよろしくおねがいします。