Nreal Light でキャラクター表示

#はじめに
2020年12月1日に発売されたスマートグラス、**NrealLight（エンリアルライト）**
今回はそこにUnityを使用してキャラクターを表示するまでのことを書いていきます。
↓NrealLight越しに見たままキャプチャーする方法が分からないので、ちょっと見え方が違う…
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/837803/dc35d4b2-aaaf-8798-3467-e06cc37090f4.png" width="300">

#NrealLightとは？
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/837803/0588bce6-8bbc-bf35-c958-1906f619ed62.jpeg" width="400">
詳しくはこちらを見て頂けると…
https://news.kddi.com/kddi/corporate/newsrelease/2020/11/10/4778.html

大雑把に言うと、スマートフォンに接続してXR技術を楽しめるスマートグラスです。
ミラーリングモードを使えばYoutubeなどを空間上に映し出して見ることも可能なので電車などで周りを気にせず動画を楽しむことも出来ます。
ケーブルがあるのでちょっとあやしい感じに見えますが…（笑）
※ 対応しているスマートフォンには注意が必要です。

#開発環境
・Windows10
・Unity2019.4.16f1
・Android SDK 8.0（APIレベル26）
・NRSDKForUnity_1.4.8
・NrealLight（Developer Kitではないものです）
・Xperia 5 II SOG02（Nreal Lightを使用するには、ビルド番号58.0.C.11.142以降が必須）

#流れ
NrealLight DeveloperKitとUnityでの開発手順は公式サイトに書いてありますので
それを参考にしながら進めていきます。
https://developer.nreal.ai/develop/unity/android-quickstart

##基本的な下準備
Android開発は初めてという人向けの簡単な説明になります。（Unityはある程度使える前提）
Unityのインストール、Android SDKのインストール、UnityのAndroidSDKパス設定、Android Debug Bridge（adb）コマンドのパスを設定、Androidの開発モード設定 に触れています。
そんなの必要ないという人も多いと思うので別記事での説明になります。
https://qiita.com/yambowcto/private/918f6eefd103d09f5e1b

##Unityプロジェクト設定
・テンプレートを3Dにしてプロジェクトを新規作成します。
・メニューのFile > Build Settings で Build Settings ウィンドウを開きます。
・Platform で Android を選択し Switch Platform で変更します。
・同ウィンドウ内の Player Settings ボタンを押して Project Settings ウィンドウを開きます。
・Project Settings ウィンドウ内の Player 設定を変更します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/837803/05a9978a-a1a6-acd8-c1e2-668fcc21da5d.png" width="800">
　※ Target API Level は level 26～29 で設定する必要があり、Android 11は現時点で非対応。
　　 また、Android 10の場合はAndroidManifest.xmlを変更する必要があると書かれてます。
　　 キャプチャー機能等使わなければ変更しなくても大丈夫かな？

・Project Settings ウィンドウ内の Quality 設定を変更します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/837803/133ef5f2-e145-0811-2ce1-667d3671e7d7.png" width="800">
　※ Skin Weights はデータ次第ですが、大抵は4 Bonesにしてあげないと破綻します。

##NRSDKForUnityパッケージのインポート
公式サイトからNRSDKForUnity_1.4.8をダウンロードして、ダブルクリックするなりしてインポートします。
https://developer.nreal.ai/download

##ユニティーちゃんのインポート
Unity公式サイトからユニティーちゃんのモデルデータをダウンロードしてインポートします。
https://unity-chan.com/contents/guideline

もし、<font color="Red">error CS0234: The type or namespace name 'Policy' does not exist in the namespace 'System.Security' (are you missing an assembly reference?)</font>のようなエラーが出ていたら AutoBlink.csを開いて `using System.Security.Policy;`を削除するか(使用してないので)、Project Settings > Player > Other Settings > Api Compatibility Level* を `.Net 4.x`に変更すれば大丈夫です。


##シーンの作成
メニューのFile > New Scene で新規シーンを作ります。
ProjectウィンドウのAssets > NRSDK > Prefabs にある `NRCameraRig` と `NRInput` を Hierarchyに追加します。
Assets > UnityChan > Prefabs にある `unitychan` も Hierarchyに追加します。
Hierarchyにある `Main Camera` は必要ないので削除しましょう。
unitychanの座標は `Position Y:-0.94 Z:2.56` `Rotation Y:180 `としておきます。
名前を付けてシーンを保存しておきます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/837803/bba5999b-39ca-8abc-ecb1-2b5f55ed799d.png" width="800">

##ビルド準備
さて、実際に作ったアプリをスマートフォンにインストールする簡単な方法としては、スマートフォンをUSBケーブルでPCに繋いで Build And Run を実行することですが、今回はNreal Lightをスマートフォンに接続しないと動かないアプリなので作業のたびにケーブルの付け替えを行う必要が出てしまいます。なので、Wi-Fi経由でインストールできる準備をしましょう。

下準備のadbコマンドのためのパス設定をしていることを前提に進めます。
まずはandroidスマートフォンをUSBケーブルでPCに繋ぎます。
※ 開発者向けオプションのUSBデバッグをONにするのを忘れずに！
　 また、スマートフォンに対して何かしようとすると`許可`の確認が結構でるので
　 移行の作業で出た場合には内容を確認しつつ基本的にOKします。

コマンドプロンプトを起動し、`adb tcpip 5555` を打ち込みEnterを押します。
スマートフォンのIPアドレスを確認（自分のだと、設定 > デバイス情報で見れます）してから
`adb connect IPアドレス`を打ち込みEnterを押します。
自分の場合Enter押した後に失敗と出ますが、スマートフォン側に許可の確認が出てるので許可をすると大丈夫です。
最後にスマートフォンとPCの接続を外して `adb devices`と打ち、認識できていればOK。
![2021-01-13_11h28_32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/837803/3b8d7166-1507-6ea6-4cba-dc7b64c2e69c.png)

##スマートフォンにNebulaをインストール
NrealLightアプリを動かすためにはNebulaのインストールが必要です。(違ったらゴメンナサイ)
なので、Google PlayからNebulaをインストールします。(↓のやつです、同名のアプリに注意)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/837803/5e1d0f90-d4da-5e11-790f-c042172309c5.png" width="200">
nebula nreal で検索すると上の方にくると思います。
スマートフォンのソフトウェアのバージョンが条件を満たしていないとNreal Lightを接続したときのNebulaの挙動がおかしくなってしまうので注意してください。（自分はそこで詰まりました…）

Nebulaを起動してセットアップを行います。
言われるがまま許可をしながら進めていきます。すると最後にグラスを付けた時のチュートリアルに進みます。


##ビルド
いよいよビルドです。
メニューのFile > BuildSettings でビルド設定を開きます。
Wi-Fi接続が上手くいっていれば、Run DeviceにIP名が入ったデバイスがあるはずです。なければRefreshで情報を更新します。
あとはBuild And Runボタンを押すとビルドが開始され、続いてインストールされます。
※ Nebulaが起動してなければ`Please connect your Nreal Light Glasses.`と出ます。
インストールしたアプリはNebulaのメニューから起動することができます。
これでキャラクターを表示することが出来ます。
操作方法はAPPボタン長押しでポインターリセット、ホームボタン長押しで終了になります。
以上、お疲れさまでした。

##おまけ
ここからはシーンにもうちょっとだけ機能を加えてみたいと思います。
まず、HierarchyにCreateEmptyでGameObjectを作成し、その子供にunitychanを移動。
この時、GameObjectのTransformの値はリセットしておきます。
Demoにある`TargetModelDisplayCtrl`を改良した以下のスクリプトをAddComponentでGameObjectに追加します。

```csharp:TargetModelDisplayCtrlEx.cs
using NRKernal;
using UnityEngine;

namespace Test
{
    public class TargetModelDisplayCtrlEx : MonoBehaviour
    {
        public Transform modelTarget;

        private Vector3 m_AroundLocalAxis = Vector3.down;
        private float m_TouchScrollSpeed = 10000f;
        private float correctZ = 0.01f;
        private Vector2 m_PreviousPos;

        void Start()
        {
            ResetModel();
        }

        private void Update()
        {
            if (NRInput.GetButtonDown(ControllerButton.TRIGGER))
            {
                m_PreviousPos = NRInput.GetTouch();
            }
            else if (NRInput.GetButton(ControllerButton.TRIGGER))
            {
                UpdateScroll();
            }
            else if (NRInput.GetButtonUp(ControllerButton.TRIGGER))
            {
                m_PreviousPos = Vector2.zero;
            }
        }

        private void UpdateScroll()
        {
            if (m_PreviousPos == Vector2.zero)
                return;
            Vector2 deltaMove = NRInput.GetTouch() - m_PreviousPos;
            m_PreviousPos = NRInput.GetTouch();
            float x = Mathf.Abs(deltaMove.x);
            float y = Mathf.Abs(deltaMove.y);
            if (x > y)
                modelTarget.Rotate(m_AroundLocalAxis, deltaMove.x * m_TouchScrollSpeed * Time.deltaTime, Space.Self);
            else
            {
                Vector3 v = modelTarget.localPosition;
                v.z += deltaMove.y * m_TouchScrollSpeed * Time.deltaTime * correctZ;
                modelTarget.localPosition = v;
            }
        }

        public void ResetModel()
        {
            modelTarget.localRotation = Quaternion.Euler(0.0f, 180.0f, 0.0f);
        }
    }
}
```
InspectorでそのコンポーネントのModel Targetにunitychanを設定します。
これにより、アプリ中の操作で上下にスライドするとキャラクターが前後に移動、左右にスライドするとY軸回転を行うようになります。


#おわりに
説明があまり上手くないかもしれませんが、いかがでしたか？
物凄く大雑把に言うと、**動作環境を満たす**、**Nebulaを入れる**、**適切なプロジェクト設定**、**NRSDKForUnityを使う** というところだけ注意すればOKだと思います。

さて、2021年に入って新たなスマートグラスの情報なども出てきています。
値段がもっとお手軽になって、街中でスマートグラスをしてても違和感がない時代が来るといいですね。

#ユニティちゃんライセンスについて
![ユニティちゃんライセンス](http://unity-chan.com/images/imageLicenseLogo.png)
この作品は[ユニティちゃんライセンス条項](https://unity-chan.com/contents/license_jp/)の元に提供されています
ユニティちゃんを使用する際は、上記ライセンスをよく読んで使用しましょう。