吉良吉影になりたいのでARでスタンドを発現・操作してみた

# はじめに

こんにちは。
ジョジョ好きなXRクリエイターの [もふるね](https://twitter.com/mofurune_k) です。

今回作るものは、ARグラスで3Dモデルの召喚・操作を行えるアプリです。
制作期間は3Dモデル制作に１ヶ月、Unity開発に２週間です。

開発環境
・Blender 2.93
・Unity 2021.3.29f1
・NRSDK v1.10.2
使用機材
・Xreal Light
・XREAL Light Devkit（またはXreal Light対応スマートフォンでも可能）

先に完成したものをお披露目しておきます。
<iframe width="560" height="400" src="https://www.youtube.com/embed/Kk5VSxohyk8?si=qbBClDbOo6OcV7Rp" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>


# 目次

・3Dモデル制作
　・モデリング
　・テクスチャ
　・走行するアニメーションを作る
　・エクスポート
　・おまけ
・Unity作業
　・ハンドポーズをトリガーにする
　・ﾆﾌﾞﾆﾌﾞﾆﾌﾞﾆﾌﾞパーティクル
　・ビルド
・まとめ
・終わりに


# 3Dモデル制作

「ジョジョの奇妙な冒険第4部」に登場する吉良吉影のスタンド「キラークイーン」の第二の爆弾「シアーハートアタック」を作ります。
流れは「モデリング→テクスチャ→シェイプキー→エクスポート」の順で行いました。


## モデリング

モデリングの際は正面図と右から見た図を用意すると、並行投影の状態でテンキーの1,3を押して輪郭を確認できるのでおすすめです。
履帯部分は配列モディファイヤとカーブモディファイアを用いました。履帯は一つのブロックが大量に連なっているので、ポリゴン数が増大するので注意です。

https://www.youtube.com/watch?v=BAZONtadGmI

![SHA-Modeling.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518924/ed40f643-d7d5-c7ca-b576-9ff0d310c445.jpeg)


## テクスチャ

リアルな質感を表現するためにアンビエントオクルージョン（以下AOと表記）を行いました。
AOとは、影をベイクする（テクスチャに焼き付ける）手法のことです。

<img width="300" alt="SHA-AO.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518924/f30c1068-6165-e3c1-5cb6-a63d42ddc513.jpeg">

※左がAO前、右がAO後


## 走行するアニメーションを作る

これを実現するには2つの方法があります。
1. 配列モディファイアとオブジェクトコンストレイントを用いる
　車体の移動と履帯の回転アニメーションの同期がとれました。しかし、Blender上では動作するのですが、Unityに持っていくためにfbx化すると、モディファイアが適応されアニメーションが壊れてしまうのでこの方法は使えませんでした。
2. シェイプキーを用いる
　履帯が回転すると考え、一つの履帯のブロックが回転前の隣接する履帯のブロックの位置に重なるまでのメッシュの移動を6段階に分けてシェイプキーとして登録します。そしてアニメーションとして6つのシェイプキーの値を1フレームごとに入れ替わる形で1.00にします。また、タイヤの回転を周期的にしたいので、60フレームで1周期となるようにアニメーションを作ります。
![SHA-Ani.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518924/845c1693-bac3-e157-ff95-292f884cf633.gif)
※0～5フレーム間の履帯の動き。履帯をなめらかに回転できた。

（より効果的でfbx化が可能なアニメーションの作り方を知っている方がいましたら、ご教授ください）


## エクスポート

最後に、作成した3DモデルをFBXファイルとしてエクスポートします。
エクスポートの設定は以下の通り
　内容>オブジェクトタイプ　　　　 ：メッシュをオン
　トランスフォーム>スケールを適用 ：すべてFBX
　アニメーションをベイク　　　　　：アニメーションをベイクをオン
　　　　　　　　　　　　　　　　　　全ボーンのキー・NLAストリップ・全アクション・強制的にキーを挿入はオフ


## おまけ

シェイプキーを用いて破壊された状態に切り替えられるようにしました。

<img width="300" alt="SHA-Fin.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518924/582b8026-e869-7cbd-4eeb-ad6ec448417d.jpeg">
<img width="300" alt="SHA-Fin2.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518924/b534714c-43ca-f788-0df1-c387e062b538.jpeg">

<iframe　width="315" height="650" src="https://www.youtube.com/embed/8vFQM6Kifb0?si=5CDaIzZHF7-rOoy4" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>


# Unity作業

先程作ったFBXファイルをUnityに持ち込みます。
Xreal Lightの開発にはNRSDKが必要なので、XREALのアカウントを作って「NRSDK v1.10.2」をダウンロードします。

https://developer.xreal.com/download

以下のurlはNRSDKの機能と詳細が書いてあります。気になったら読もう。

https://xreal.gitbook.io/nrsdk/v/v1.10.2/nrsdk-fundamentals/core-features

NRSDKをUnityにインポートしたら、Assets>NRSDK>PrefabsにあるNRCameraRigとNRInputをヒエラルキーに置きます。

シアーハートアタックのFBXファイルをヒエラルキーに置きます。
NRCameraRigに必要なカメラがすでに用意されているので、ヒエラルキーのMainCameraは消去します。

NRInputを以下の通りに設定します。
Overrude Camera Center：NRCameraRig>CehterAnchor
Raycast Mode：Gaze
Input Source Type：Hands
![NR01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518924/6c8fded0-7ab4-6860-cd9c-b9db9855f43d.png)

ヒエラルキーのNRInput>RightにAssets>NRSDK>Prefabs>Hands>NRHand_Rを、同じくLeftにNRHand_Lを置きます。
また、NRHand_RとLの子にあるNRHandCapsuleVisual_RとLを選択肢、インスペクターでチェックを外します。（手のモデルを見えないようにしただけです。）

ここで任意ですが、指先の判定を見えやすくするために、以下の記事を参考にパーティクルを出現させるスクリプトを書きます。

https://zenn.dev/alucky7th/articles/78ad088cfaa819

## ハンドポーズをトリガーにする

こちらの記事を参考にして作りました。この記事を書いてくれた「Y. Araki」さんに感謝します。

https://zenn.dev/alucky7th/articles/926f5cb50d1734#%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88%E3%83%A9%E3%82%A4%E3%83%88%E3%82%92%E4%BD%9C%E6%88%90

まずは以下のものを用意します。
・爆発パーティクル（Unity公式のアセットを以下のurlからダウンロードしてインポート）
・スイッチ音
・爆発音

https://assetstore.unity.com/packages/slug/127325?aid=1011lGbg

次にスクリプトを作ります。名前はPinchTriggerSHAにしました。

このPinchTriggerSHAスクリプトをヒエラルキーのNRHand_Rに付けます。

そして、スクリプトの中身を書き込んでいきます。
```c#:PinchTriggerSHA.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using NRKernal; //NRSDKの機能を使用する場合は必ず記載。

public class PinchTriggerSHA : MonoBehaviour
{
    public HandEnum handEnum; //ハンドトラッキングの様々な情報を参照できる。
    private bool Pinched = false; //ピンチポーズをしたらtrueに変える。
    private float triggerLine; //どれぐらいの間ピンチポーズをしていたらオンにするかの数値を保管。
    private float triggerCharge; //ピンチポーズをしている間triggerLineと同じ数値になるまで増加していく数値を保管。
    public GameObject particlePrefab;
    public Transform spawnPoint;
    public AudioClip sound1;
    public AudioClip sound2;
    private AudioSource audioSource;

    void Start()
    {
        triggerLine = 0.3f;
        triggerCharge = 0.0f;
        audioSource = GetComponent<AudioSource>();
    }

    void Update()
    {
        CheckPose();
    }

    void CheckPose()
    {
        var handState = NRInput.Hands.GetHandState(handEnum); //常に手の状態をチェックして更新する。
        if (handState == null)
        {
            return;
        }
        else if (handState.isPinching) //ピンチポーズしているかどうか判定。
        {
            triggerCharge += Time.deltaTime; //triggerChargeの数値を増加させる。
            if (triggerCharge > triggerLine && Pinched == false) //triggerChargeの数値がtriggerLineの数値まで到達するとオン。
            {
                Pinched = true;
                triggerCharge = 0.0f; //増加した数値をリセット。

                audioSource.clip = sound1;
                audioSource.Play();
                StartCoroutine(PlaySound2AfterDelay());
            }
        }
        else if (!handState.isPinching)
        {
            Pinched = false;
            triggerCharge = 0.0f;
        }
    }

    private IEnumerator PlaySound2AfterDelay()
    {
        yield return new WaitForSeconds(0.3f);

        audioSource.clip = sound2;
        audioSource.Play();

        // プレファブをインスタンス化してパーティクルを生成
        GameObject particleObject = Instantiate(particlePrefab, spawnPoint.position, Quaternion.identity);

        // パーティクルシステムを取得して再生
        ParticleSystem particleSystem = particleObject.GetComponent<ParticleSystem>();
        if (particleSystem != null)
        {
            particleSystem.Play();
        }

        // パーティクル再生後、必要ならば一定時間後に破棄
        Destroy(particleObject, particleSystem.main.duration);
    }
}
```
スクリプトの解説をします。
NRSDKのDeveloper GuideのDetails Of HandStateのページを見ると、ハンドジェスチャーに関連した値を取得できることがわかります。

https://xreal.gitbook.io/nrsdk/v/v1.10.2/development/hand-tracking

今回使うのは「bool isPinching = handState.isPinching;」の値です。ピンチしてるかどうか、つまり親指と人差指が接しているかどうかをbool値で取得できます。
[handState.isPinching]がTrueの際に、[triggerCharge]の値を段々と増加させ0.3を超えると、スイッチ音と爆発音が間隔を開けて流れ、爆発パーティクルを生成して再生します。

PinchTriggerSHAの設定は以下のように行います。
Hand Enum：Right Hand
Particle Prefab：アセットの爆発パーティクル（SmallExplosion）
Spawn Point：ヒエラルキー上で空のオブジェクトを作り、爆発させたい位置に移動させてアタッチ
Sound1：スイッチ音
Sound2：爆発音
![NR02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518924/95a122d3-6061-2f81-dd61-45f7af012092.png)

ヒエラルキーのNRHand_RにAudio Sourceコンポーネントを付けます。これがないと音がなりません。
Spatial Blendを1にしておきます。
![NR03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518924/d58aa091-25e1-9b69-5e48-e1df4d229546.png)


## ﾆﾌﾞﾆﾌﾞﾆﾌﾞﾆﾌﾞパーティクル

やはりジョジョにこれは欠かせないッ！

<img width="600" alt="NR04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518924/3eead039-26e1-6c73-353e-18fad7e9a4aa.png">


「ゴ」の透過画像が必要なので、フォントを用意してペイントソフトで作ります。
このフォントは「ア」から「ン」、半音、感嘆符、濁点などがあり、Shiftを押しながら打つと様々な種類の「ゴ」が打てるという優れもの！グレートですよ、こいつはァ！

http://www2.gol.com/users/glow/jojo_font.html

<img width="150" alt="TexGO.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518924/e3fcb16c-c519-0d50-603b-38d9365a407a.png">

作った透過画像をインポートし、Alpha SourceをInput Texture Alphaにし、Alpha Is Transparencyにチェックをつけ、Applyを押します。
![NR05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518924/76c5accb-7777-20b0-fd4b-448e8fc97217.png)
マテリアルを作成し、シェーダーをMobile/Particles/Alpha Blendedにします。
![NR06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518924/f0ec258d-f316-76c1-eff7-ce97849a59fc.png)
ヒエラルキーでパーティクルを作成します。
設定は
　Start Speed：0.1
　Start Size：0.1
　Max  Particle：100
Emission
　Rate Over Time：1.3
Shape
　Shape：Cone
　Radius：0.34
Renderer
　Rebder Mode：Vertical Billboard
　Material：先程作った「ゴ」のマテリアルを適応


## ビルド

Androidでビルドしてapkファイルを作ります。
次に、PCとXREAL Light Devkitを接続して、Quick Installフォルダにapkファイルを入れます。
そして、Xreal LightとXREAL Light Devkitを接続して、Quick Installを起動し、インストールを完了させます。

・・・これにて全工程が完了しました！👏
さぁアプリを起動して遊んでみましょう！

<iframe width="560" height="400" src="https://www.youtube.com/embed/Kk5VSxohyk8?si=qbBClDbOo6OcV7Rp" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>


# まとめ

1. 3DモデルをBlenderで作り、FBXファイルとしてエクスポートする
2. UnityにFBXファイルを持ち込み、NRSDKをインポートする
3. ハンドポーズをトリガーにするスクリプトを作成する
4. ビルドしてXreal Lightにインストールする
5. アプリを起動し、好きなだけシアーハートアタックを爆破する


# 終わりに

来るか！ジョジョラー達・・・

『吉良吉影になれるARアプリ』はスタンド使いになりたい「一心」で開発したアプリだ！

インストールして来いッ！
「Xreal Light」を使ってみろッ！
何秒　楽しめる？

このわたしに感想を送ってくるがいい！

その限界の「ワクワクさ」が
再び　きっと！！
『もっともっと面白いARアプリ』を発現させるのだッ！

![NR07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518924/f04f44ba-7c49-473f-45bd-a2d22ae9ed2f.png)

いいや！ **「限界」** だッ！押すねッ！
 **『今だッ』！**
カチッ
![NR08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518924/9c55f611-e7ea-8816-102b-b4d1bd18e2f1.png)

ドグオォォォォォォ

やっ！
やったぞッ！
発動したぞッ！

・・・

・・・

フ・・・フハ・・・
フハハハハハハハハハ

できたぞ・・・フフフ
開発できたんだ・・・ハハハ
『シアーハートアタックを大量召喚できるARアプリ』を新たに開発できたんだ！
<iframe width="560" height="400" src="https://www.youtube.com/embed/vp5hhBrzVrM?si=VKK058S6M-U_T8dP" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
フハハハハハハハハハハハハハハハハハハハハハハハハハ

ハハハハハハハハ
シアーハートアタックが増えたぞッ！

これで　私は
吉良吉影になれるッ！
　
　
　
はい、ここまでお付き合いいただきありがとうございました。
右手で爆破させるところまでを作って一旦完成にしたんですが、左手も使えることに気づきまして、これで大量召喚をしよう！と思い立ちました。
思い立っちゃったんです...
そこからが大変で、複数のシアーハートアタックを出現させて位置と物体の情報を記録し、同時爆破と3Dモデルの消去をする必要があり、頭を唸りに唸らせながらなんとか作り上げました...！
作るのは難しいですが、自分の思い描いたものが実現できると、気分が最高にハイになりますね！
自分で作って使ってみて、Xreal Lightはとても可能性があるものだと感じました。
もっともっと創作していきたいです！

「吉良吉影になれるARアプリ」と「シアーハートアタックを大量召喚できるARアプリ」で遊んでみたい方は、XのDMなどでお伝え下さい。apkファイルをお渡しします。

今回作ったシアーハートアタックの3DモデルはVRChatで使えるようにUnityPackage化して配布しているので、興味が出た人はどうぞお使いください。

https://booth.pm/ja/items/4676807

https://booth.pm/ja/items/4675058