20200225のUnityに関する記事は8件です。

【Unity】blenderのことはよく分からないけど爆速でオブジェクトの上にクルクル回るポインタを作成したい

はじめに

オンラインゲームでよく敵オブジェクトの頭上にクルクル回ってる矢印がありますよね。あれを作ります。
gorilla.gif

ゴリラはAssetStoreのGorilla Characterから拝借しました。

ゴリラ可愛い。

矢印を作る

四角錐はUnityにはないので自分で作らないといけません。 Blenderで作ります。Blenderは無料で使えていいね。 滑らかな3Dオブジェクト作りたいならSculptrisもおすすめ。

さて、blenderを立ち上げると以下のような画面が立ち上がる。

スクリーンショット 2020-02-14 21.09.15.png

①立方体にカーソルを合わせて右クリックで選択(オレンジ色の線でほんのり囲まれていればok)

②左に「削除」ボタンがあるので削除実行する。同様にカメラとライトも消す。

③画面の中心を左クリックでカーソル移動、左下の方に「add」あるいは「追加」があるので、クリックしてメッシュ->円錐と選ぶ

④左下に円錐の設定画面が小さくでてくるので、頂点を4、フィルタイプをなし、にします。(下画像)
スクリーンショット 2020-02-14 21.15.37.png

⑤作成できたら右側のアイコンから、下画像で選択してるアイコンを選び、その中にある新規を選びます。
スクリーンショット 2020-02-14 21.19.51.png

⑥ディフューズから好きな色に設定します。(下画像)
スクリーンショット 2020-02-14 21.22.10.png

以上で作成終了です。ファイル->保存 します。
保存できたらUnityの適切なフォルダにドラッグアンドドロップして取り込みます。

このプレハブをゲームシーンの適当な場所に配置して反対向きに回転させれば、、
スクリーンショット 2020-02-25 17.51.20.png

真っ黒ですね。これはライトの関係で、上から光を当ててるような設定にしてるので全体が影になってしまっています、、

真下に上向きスポットライトを置いて解決したことにします。

スクリーンショット 2020-02-25 17.59.14.png

これでポインタが完成です! ゴリラの上に移動させましょう。

スクリーンショット 2020-02-25 18.01.32.png

ポインタを回転させる。

以下のコードをUpdate関数内に書いて、ポインタにアタッチします。

// ワールドのy軸に沿って1秒間に90度回転
transform.Rotate(new Vector3(0, 90, 0) * Time.deltaTime, Space.World);

これで実行すると、最初に貼ったgifのような動作を実現することができます!!

おしまい

長くなってしまったので、ポインタの上に文字を表示する方法などはまた別の機会に載せたいと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity】オープンワールドゲームでよくある近づいたらボタンが表示されるオブジェクトの実装

はじめに

gorrila_mypage.gif
上のgifのように、近づいたらMyPageへのボタンを表示してくれるマイページゴリラを作成します。
ただボタンで画面遷移するよりグッとゲームっぽくなりますね!
ゴリラや黄色いポインタの設置は別記事で書いたので以下を参照
【Unity】blenderのことはよく分からないけど爆速でオブジェクトの上にクルクル回るポインタを作成したい

橙色で書かれたMyPageを表示する

簡単に説明すると、MyPageという文字の画像を用意し、それをゴリラの上に置いているだけです。

文字を画像化する

MyPageTitle.png

僕はMediBangPaintProという無料のペイントツールを使って作りましたが、webでつくれるツールもあるのでよしなにしてください。ここは割愛します。

ただ、背景は透過にしましょう。でないと背景まで写ってしまいます。

Canvasを設置し、その中にImageオブジェクトを設置して貼り付ける

1.GameObject->UI->CanvasでCanvasを設置
2.設置したCanvasのInspectorから、RenderModeをWorld Spaceにし、Event CameraにMain Cameraを設定

これで自分の好きな位置にCanvasを移動できるようになるので、位置やサイズを調整します。僕はこのCanvasをゴリラの子オブジェクトにして、Positionをすべて0にしました。

次に先ほど作成した文字画像をUnityに取り込みます。

3.先ほど作成した文字画像をUnityに取り込みます。Projectビューで適当にフォルダを作成し、そこに文字画像をドラッグアンドドロップします。
4.画像のInspectorビューから、TextureTypeをSprite(2D and UI)に設定。

これで画像を取り込み、表示する準備が完了しました。
最後にこの画像をCanvas内に表示します。

5.GameObject->UI->Imageで、先ほど設置したCanvas配下に画像オブジェクト作成
6.ImageオブジェクトのInspectorで、SourceImageに先ほどの画像を設定し、PreserveAspectにチェックを入れます。

以上で文字画像の表示が完了しました! あとサイズは自身の仕様に合わせて変えましょう。

プレイヤーがゴリラに近づいたことの判定処理

これは以下の画像のようにゴリラにColliderを二つアタッチすることで実現します。

スクリーンショット 2020-02-25 19.04.25.png

ゴリラが透過しないように一つCapsuleColliderをつけます。
もう一つはプレイヤーがゴリラの近くにいることを判定するためのColliderなので、ゴリラ前方に少し大きめのSphereColliderをアタッチします。
SphereColliderだけisTriggerにチェックを入れておきましょう。こうすることでオブジェクトがSphereColliderに衝突せず、CapsuleColliderに衝突するようになります。

次にプレイヤーが近づいた時の処理をコードで実装します。
isTriggerにチェックを入れているので、OnTriggerStayでプレイヤーがゴリラの近くにいること、OnTriggerExitでプライヤーがゴリラから遠ざかったことを判定します。

プレイヤーオブジェクトにPlayerタグをつけ、以下のコードをscriptに書いてゴリラにアタッチします。
なお、今回は長くなってしまうため、画面遷移のボタン等設置したパネルはあらかじめ作っているものとします。

void OnTriggerStay(Collider other)
{
    if (other.CompareTag("Player"))
    {
        //プレイヤーがゴリラ圏内にいるときの処理
        //ボタン等を設置したPanelを表示させる。
        Panel.SetActive(true);
    }
}
void OnTriggerExit(Collider other)
{
    if (other.CompareTag("Player"))
    {
        //プレイヤーがゴリラ圏内から出た時の処理
        //Panelを非表示にする。
        Panel.SetActive(false);
    }
}

これで冒頭に貼ったgifのように、プレイヤーが近づいた時だけボタンを表示するゴリラの実装ができました!!

おしまい

簡単すぎる説明になってしまったかもしれません。
わかりにくいところなどあればコメントいただければ随時追加します。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Unity] DOTween を使いまわしたい君へ

最初に

DOTween のシーケンスを使いまわしたい君へ」と内容の9割がかぶっているので、説明を見たくばそちらをどうぞ。

結論

これを足す。

.Pause()
.SetAutoKill(false)
.SetLink(gameObject);

実行時はこれ。

tweener.Restart();

毎回書くのしんどいので、関数にしましょう。

using DG.Tweening;
using UnityEngine;

public static class Utilities {
    public static void MakeTweenerReusable(Tweener tweener, GameObject linkTarget) {
        tweener.Pause().SetAutoKill(false).SetLink(linkTarget);
    }
}

サンプル

using DG.Tweening;
using UnityEngine;

public class Ahan : MonoBehaviour {
    Tweener tweener;

    private void Start() {
        tweener = transform.DOScaleX(0f, 1f);
        Utilities.MakeTweenerReusable(tweener, gameObject);
    }

    private void Update() {
        if (Input.GetButtonDown("Fire1")) {
            tweener.Restart();
        }
        if (Input.GetButtonDown("Fire2")) {
            tweener.Restart();
        }
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

UnityとARkitでVtuberアプリを作ってみた

はじめに

最近の流行りのVtuberになれるアプリ作ってみました。

このアプリは2つのアプリから成り立っていて
iPhone側でフェイスキャプチャー用が
PC側(Windows10)でLive2Dの制御用です。


動画左がiPhoneのアプリで、右側がPCアプリです。
※この動画では下のサンプルコードで取得してる部位以外も使用しています。

開発環境

Unity2019.2.15f1
Windows10
iPhoneXR
ios13.3
Mac 10.15.1
Xcode 11.3
ARFoundatinは、Unity公式のGitHubからARFoundationの最新プロジェクトをクローンしてきます。
ARFoundatinリンク
Live2DモデルはCubism3.0桃瀬ひよりを使用しました。

※ARFoundationに関しては自分も勉強途中なので間違っているところもあるかもしれません

iPhone側のアプリについて

今回はARKitFaceBlendShapesのシーンをメインで使っていきます。

iPhone側のアプリで参考にするのはARKitBlendShapeVisualizer.csになります。
今回はこれをもとに改造していきます。

ARKitBlendShapeVisualizerの簡単な説明

ARFaceコンポーネントを取得していて、これを軸に作成されています。
ARFaceは顔情報の更新が検知できるので、ここのupdatedに更新ごとの処理を登録していく形になります。

データの取得

c#ARKitBlendShapeVisualizer.cs
 void UpdateFaceFeatures()
    {
        if (skinnedMeshRenderer == null || !skinnedMeshRenderer.enabled || skinnedMeshRenderer.sharedMesh == null)
        {
            return;
        }  

        using (var blendShapes = m_ARKitFaceSubsystem.GetBlendShapeCoefficients(m_Face.trackableId, Allocator.Temp))
        {
            foreach (var featureCoefficient in blendShapes)
            {
                int mappedBlendShapeIndex;
                if (m_FaceArkitBlendShapeIndexMap.TryGetValue(featureCoefficient.blendShapeLocation, out mappedBlendShapeIndex))
                {
                    if (mappedBlendShapeIndex >= 0)
                    {
                        skinnedMeshRenderer.SetBlendShapeWeight(mappedBlendShapeIndex, featureCoefficient.coefficient * coefficientScale);
                    }
                }
                switch (featureCoefficient.blendShapeLocation)
                {
                    case ARKitBlendShapeLocation.EyeBlinkLeft:
                        motionDate.Leye = featureCoefficient.coefficient;
                        break;
                    case ARKitBlendShapeLocation.EyeBlinkRight:
                        motionDate.Reye = featureCoefficient.coefficient;
                        break;
                    case ARKitBlendShapeLocation.JawOpen:
                        motionDate.Mouth = featureCoefficient.coefficient;
                        break;
                }
            }   
        }
    }

基本的に参考にしているscript内のUpdateFaceFeaturesメソッドで実装されています。

NativeArrayの中に構造体で格納されているので必要な部位のデータだけ
取得します。

foreachを使って構造体ごとに取り出していきます。
部位の選択はstruct内の部位情報と自分の欲しい部位が一致しているかで行っています。
ARKitBlendShapeLocation(enum)で部位指定できます。

switch文部分が追加したコードです

データ格納用クラスを作成し
格納クラス→JSON→byteと変換しPCに送信していきます
送信タイミングは顔データが更新されると送信としました。

送信方法はUDPで実装しています。
PC側が受信、iPhone側で送信で実装しています

よく使われるUDPの通信です。
すでに多くの資料が公開されているので通信部分は省略します。
(UDP C# 実装で検索)

ここからはPC側のアプリについてです

データが受信できたら復元しLive2Dに適用していきます
データを復元したタイミングでnullチェックしておくのがオススメです

モデルへのデータ適用はLive2D公式のドキュメントのパラメーター更新と同じ方法です(ドキュメントリンク)

データ適用時の注意点だけ記述します

  1. 取得したデータは個人差があるので1.0〜0.0でキレイに取得できることは無いです なので各部位ごとに平均最大値と平均最小値を算出し 正規化した数値を適用したほうがきれいに見えると思います
  2. 目の開きのデータはLive2Dと最大最小が逆で取得されるので数値の変換が必要になります
  3. 部位によって最大最小値が異なるのでその対応も必要になります
  4. 純粋なARkitの数値が入っているという感じでない部位がある。

作っている中で躓いたポイントです

Wi-Fiでの通信ができない

PC側でWi-Fiの設定をプライベートに変更
あとはポートの設定も変えとく(windows10 ポート開放で検索)

iPhone側でWi-Fi設定からプロキシ設定を手動
サーバに使用するIPアドレスを
ポートに使用するポート番号を入力して保存

上の設定しても通信ができない

多分ルーターとかのセキュリティ問題 (学校の学科専用Wi-Fiでやったらできなかった)

急に接続が切れた

どうやらiPhoneで残り電池残量等のポップアップが出ると接続が切れるっぽいので再接続

その他

NativeArrayの部分を改造するときは開放処理を忘れずに

NativeArrayは指定したAllocatorのタイプごとに開放処理が必要です
今回は、Tempを指定したので1フレーム以内です!
詳しくは Unity NativeArrayで検索!
(UnityDOTSなどでも使われるので、これからは必須の知識になりそう)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Hololens開発入門 環境構築から3DモデルをHololensで鑑賞するまで

はじめに

今回は備品のHololensを使って開発をしてみたので、そのフィードバックです。

記事一回全部消えて書き直しになってます…保存大事。

開発環境

  • Windows10
  • WindowsSDK
  • Unity2018.4.17f1
  • VisualStudio2019
  • MRTK
  • Hololens本体

この開発環境を作ります。

OS

OSはWindowsのみです。

私は普段Macを使っていますが、今回はwinを使いました。

Macしかない場合は仮想環境でもできるという記事を見かけたので、仮想環境を組んでください。

WindowsSDK

SDKはMicrosoftのDLページでDLしてください。

https://developer.microsoft.com/ja-jp/windows/downloads/windows-10-sdk/

Unity

Unityは2018.4.17f1を使いました。
過去のバージョンのUnityのDLページからDLしてください。

https://unity3d.com/jp/get-unity/download/archive

VisualStudio

VisualStudioは2019をDLしてください。

https://docs.microsoft.com/ja-jp/visualstudio/windows/?view=vs-2019

MRTK

MRTKはUnityにインポートするHololens開発用のパッケージです。

MRTKはGitHubからDLできます。

MRKTのReadmeが開発する上でわかりやすいので一読をお勧めします。

https://github.com/microsoft/MixedRealityToolkit-Unity/blob/mrtk_development/README.md

パッケージのDLはリリースページでDLしてください

https://microsoft.github.io/MixedRealityToolkit-Unity/Documentation/GettingStartedWithTheMRTK.html

オプションはいらないです。
Microsoft.MixedReality.Toolkit.Unity.Foundation.2.3.0.unitypackage
のみDLしてください

以上が開発に必要な物です。全てDLして揃ったら次に進みます。

Unityで開発

Unityでプロジェクトを3Dで作成します。

そしてHierarchyのMain Cameraを削除します。

Assets > Import Package > Custom package

から先ほどDLしたMRKTパッケージをパッケージを開きます。

Importを押して、パッケージをインポートします。

importが終わるとMRKTのConfiguratorが開きます。
コメント 2020-02-20 144102.png
Applyを押します。

Edit > Project Settings

からPlayerのConfigurationのScripting BackendをILCPPにします。
コメント 2020-02-20 145105.png
次に、Mixed Reality ToolkitのタブからAdd to Scene and Configureを選択します。
コメント 2020-02-20 145314.png
これで事前の準備は完了です。

Scene画面にBlenderなどで作ったモデルなど、好きなオブジェクトを配置します。

モデルがない場合は3DObjectからcubeなどをおきましょう。
コメント 2020-02-20 145838.png

これでいいなと思ったらビルドに移ります。

ビルド

ここからHololens向けにビルドします。

File > Build Settingsを開きます。

Add Opeen ScenesでSceneを追加します。

Universal Windows Platformを選択して、画像のように設定します。
コメント 2020-02-20 152427.png
設定ができたら下のSwitch Platfrmを押します。

MRKTの設定のポップアップはApplyを押します。
コメント 2020-02-20 153135.png

ここまでのBuild設定ができたら適当な場所(デスクトップ等)に書き出し用のファイルを作ってそのファイルにビルドします。

ビルドができたら書き出されたファイルを次はVisualStudioで開いていよいよHololensに作ったプロジェクトをインストールします。

VisualStudioで設定

VisualStudioでの設定の前に一つだけやっておくべきことがあります。

それは、Windowsの開発者モードへの切り替えです。

設定画面を開いて更新とセキュリティの開発者向けの項目から開発者モードにしておいてください。

Hololensも同じように開発者モードにしておきます。

開発者モードへの切り替えができたら、先ほどBuildしたファイルの中の.slnファイルをVisualStudio2019で開きましょう。

開いたら、設定を Release ×86 Divice に切り替えて、HololensとWindowsをUSB接続します。
コメント 2020-02-20 154414.png

WindowsにHololensが接続されたことが確認できたら、デバッグ > デバッグなしで開始 を押します。

ビルドが終わったらPinの入力を求められるかと思います。

PinはHololensの設定画面>更新とセキュリティ>開発者向けの画面のDevice discoveryという項目からPairをタップすると見れます

pinを入力するとHololensとWindowsがペアリングされ、Hololensにビルドされます。

完了するとUnityの画面が表示されて、自分が作成したUnityのSceneが表示されます。
20200217_220038_HoloLens.jpg
無事にキャラクターが表示されました。

まとめ

いろいろな記事を見たけど、それぞれがいろんな環境でやっていて、戸惑った。(Unity2017を使った開発の記事など)

Windowsの操作に慣れていなかった部分があった(普段mac)。

Unityでのビルド設定、VisualStudioでのリリース設定と、二段階になっていて少しややこしい部分があった。

最終的にしっかり動いてくれたからヨシ!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VFX Graph初動のススメ

VFX Graphを扱うときの注意点

  • Unityのバージョンに関する注意

バージョン:2019.3.0f6以降のもの

  • プロジェクト開始時にテンプレートシーンを選ぶとセッティングをしなくていいのでそちらをオススメする(そちらじゃないと自分はわからないとも言う)

    • こちらを選び、新しいシーンを生成する際には、Asset→Create→HD Template Sceneを選択し生成する。(このシーンは初期からHDRPで構築されているシーン)

VFX Graph(Visual Effect Graph)とは

  • そもそも、この技術(VFX)はCG側で使われていたものであり、当時は処理が重くゲーム側で使えるような物ではなかったが、グラフィックボードの進化、Unity側の努力によりノードベースで簡単にパーティクルが作れるというものである。

実際の作成方法

  1. まず前提としてHD Template Sceneでやろうとしているものとする。

  2. Asset → Create → Visual Effect → Visual Effect Graph を作成

  3. 作成したVisual Effect Graph をダブルクリック

  4. 四大処理のノードが表示されるのでそこをいじって自分の作りたいパーティクルを作成していく

実際に表示されるものがこちら ↓

スクリーンショット (50).png

できること・メリット・デメリット

  • できること
    • そもそもVFX Graphとはパーティクルシステムの一種なのでパーティクルを作成することができます。
  • メリット
    • ノードシステムでできるのでかなり手軽に作成することができる。
    • パーティクルシステムとの比較になるが、CPUで行われていた処理がGPUで行われているので、パーティクルシステムよりかなり軽い。
  • デメリット
    • 比較的最近正式リリースされたものなので、サンプル数が他と比べると少なめ。

参考にした方がいいもの

  • ブログ等で作成されているものだと、実際に作成できなかったり、HDRPのセッティングから行っていたりするので、Asset(作成されたものからの学習)やUnity Japanが出している動画を参照することを強くオススメする。(おすすめの物は引用のところに貼っておく)

引用

参考動画1:https://www.youtube.com/watch?v=Xwmdl4sbsjY

参考アセット1:https://assetstore.unity.com/packages/vfx/particles/cool-visual-effects-161342?locale=ja-JP

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VRM データをもっと Unity らしく作る

アバター向けのファイルフォーマットである VRM を公式サイトのチュートリアルに沿って作ると、Fbx 内のメッシュへの参照が切れた状態の Unity シーンが出来上がります。

多くの場合、些細なモデルや衣装の更新であっても VRM を1からを作り直す必要があり、その VRM を作るという作業が思いのほか複雑で、作成する度に思い出す・調べる必要があるかと思います。

VRM を作っていると、なんだかどうにもうまくいかない、妙に手間がかかる、その原因は Fbx へのリンクが切れている点に集約されるのだろうなと思っています。

もっと Unity らしく FBX-Linked なシーンにして、開発と量産・運用ともに気軽に対応できるようにしたい訳です。

※ VRM 書き出し用のシーンでも普段通りに Fbx 更新を追いかけるようにした状態

もくじ

はじめに

例えば単発のイベント用に専用のフェイシャルを使おう、となった場合、普段なら Fbx にそのフェイシャルを追加してやるだけで、参照が生きているメッシュには新しいフェイシャルターゲットが追加されるので、なんの苦労もありません。

メッシュの増減も追跡してくれるので、アクセサリの追加や衣装替えなども Fbx を差し替えるだけで終わります。揺れ物の設定やコリジョンも使いまわせるところは使い回し、変更部分だけを更新すれば良いわけです。

※ Fbx ファイルにブレンドシェイプを追加

今回は、更新のたびに VRM オーサリングを1からやり直すのでは無く、Fbx への参照を維持したまま VRM に書き出すことができるシーンの構築を目指します。

あわせて、VRM 以外の用途で使う Fbx をそのまま VRM オーサリングでも使えるようにする為、正規化されていない A ポーズを維持した状態の Fbx で作業を進めます。

※ 正規化された T ポーズ、の要求も VRM の厄介な問題…。

なお、今回使用している各ソフトウェアのバージョンは以下の通りです。

  • Unity 2019.2.9f1
  • UniVRM v0.53.0

VRM 用のコンポーネントの収集

まずは Fbx モデルを Humanoid として読み込み、モデルインポーターの設定の Rig > Avatar Definition > Configure... で Jaw や Eye(目線がブレンドシェイプの場合)に間違ったボーンがアサインされていないかを確認します。

その後、モデルを VRM > Export Humanoid から .vrm ファイルとして書き出し、書き出したファイルを Unity にインポートします。

--

ここまでは公式のワークフローと同じで、目的は VRM Meta コンポーネントや Blend Shape の定義ファイルを作ることです。

※ A ポーズのユニティちゃん Fbx を VRM として書き出したところ

.vrm インポートが終わると、上図のように VRM コンポーネントを含んだプレハブが自動生成されます。

このプレハブに含まれる、VrmAvatarAvatarDescritpionMeta の3つのファイルは、後で使用することになるので Ctrl+D で複製し、独立したファイルとして扱えるようにしておきます。

※ .vrm 内のアセットは Edit > Duplicate で独立したファイルとして扱えるようにしておく

※ VRM バージョン 0.53 では Prefab に内包されていますが、最新バージョンだと最初から独立したファイルとして扱えるようになっていますね。

Fbx の入れ替えが可能なシーンを作る

ここからは Unity らしいシーンを構築していきながら、無用な複製ファイルを削除してプロジェクトを整理していきます。

--

まずは .vrm インポートで作られたプレハブをヒエラルキーに追加して、コンポーネントに設定されている MetaVrmAvatar x2、AvatarDescription の参照先を、前の工程で複製したアセットファイルに差し替えます。
※ メッシュは削除することになるので、マテリアルはひとまず置いておきます。

あわせて、VRM First PersonRenderers は気が付いたら参照が外れていてエラーの原因になるなど厄介なので、Size を 0 にして全ての参照を消しておきます。アバター利用がないなら、二度と触らなくていいと思います。

※ デフォルトで全てのレンダラーが追加されていますが、VRM オーサリングの最後の最後に、必要なものだけを追加しましょう。忘れがちですが… アバター利用がない限りは必要にはなりませんし、ある程度は VRM 側が自動で対応してくれるようです。

※ 各 VRM コンポーネントの参照先を更新する(Inspector 太字部分)

続いて、Hierarchy の VRM ルートノードを右クリック > Unpack Prefab して、secondary 以外を削除し、Fbx モデルデータをルートノードの子供としてヒエラルキーに追加します。

※ モデルデータを Fbx への参照に切り替えた状態(青字部分)

これでメッシュは Fbx ファイルを参照している状態になるので、究極的には Fbx モデルの GameObject(unitychan_Fbx)を入れ替えて、VRM アバターを別のメッシュ・スケルトン構造に変更することも可能になります。

なお、モデルは書き出し時に「Force T-Pose」と「Pose Freeze」を行うので、Unity 上では T ポーズ正規化を行わずに A ポーズのままにしておきます。これは前述の通り、VRM とそれ以外の用途で使う Fbx を共通化することが目的です。

VRM アセットの更新

VRM の階層構造を変更すると、VRM ルートノードにアタッチされた Animator(Avatar) のボーンへの参照が切れた状態になるので、VrmAvatar.asset ファイルは更新が必要になります。

あわせて、VRM Blend Shape Proxy で使われている Blend Shape Avatar/Clip のプレハブ参照が .vrm ファイルになっているので、Fbx ファイルに変更する必要もあります。

※ Animator にエラーが出ているので Avatar を更新する必要がある

Avatar や Blend Shape の更新は以下のユーティリティーで行います。

VRM Tool Kit

「VRM Tool Kit リンク」
 Unity Package Manager 対応中

※ A ポーズを維持すると言いつつ、諸事情で一度 T ポーズに変換してその後キャラクターをプレハブの初期値に戻す、という作業をしています。

ブレンドシェイプの設定

アセットの更新が済んだら取り急ぎ書き出して問題の有無を確認、としたいところですが、エラー対策をしておかないと VRM への書き出しが出来ないことがあるので、先にブレンドシェイプの設定をしておきます。

インスペクタースクリプトの更新

FBX-Linked VRM の場合、PreviewEditor.cs を少し弄らないと Blend Shape Clip のインスペクター下部に表示されるプレビューやフェイシャルのスライダーが機能しません。
(プレビューと設定が出来ないだけで、設定済みのデータを扱うだけなら問題はない)

編集機能を使用可能にするためには、以下から更新されたスクリプトをダウンロードして上書きします。

UniVRM v0.53 以外を使用していて上記のファイルをそのまま使うことに抵抗がある場合は、以下の変更内容を参考にスクリプトを更新します。

※ 文字列操作を元にプレハブを取得する前に、コンポーネントの参照を辿って取得を試みるようにしています。

VRM > UniVRM > Editor > BlendShape > PreviewEditor.cs の97行目あたりに、

var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);


// ↓ ↓ ↓ 追加 ↓ ↓ ↓
if(prefab == null && 0 < (target as BlendShapeAvatar).Clips.Count)
{
   prefab = (target as BlendShapeAvatar).Clips[0].Prefab;
}
// ↑ ↑ ↑ 追加 ↑ ↑ ↑


if (prefab == null)
{
   var parent = UniGLTF.UnityPath.FromUnityPath(assetPath).Parent;
   var prefabPath = parent.Parent.Child(parent.FileNameWithoutExtension + ".prefab");
   prefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath.Value);
}
return prefab;

を追加します。

VRM ブレンドシェイプのエラー対策

VRM エクスポート時のエラー対策の為、Neutral などのウェイト設定が必要のない表情、将来的に使うかもしれないが今は設定しない表情にも、何かしらのウェイトを 0 で追加しておきます。

※ Neutral は全てのウェイトを 0 として登録する…?

プロジェクトの整理

ここまでくると、.vrm エクスポート・インポートで作成された無用なファイル群を削除できるようになります。

VRM コンポーネント収集のためだけの仮 .vrm ファイル、加えて ***.Meshes***.Textures フォルダも必要のない複製ファイルなので削除しておきます。

マテリアルが VRM とそれ以外の用途で共通であれば、***.Materials も無用なので削除してしまいましょう。

※ 無用な複製がなくなった状態

書き出しテスト

ファイルの整理が済んだら一度 VRM として書き出して、T ポーズや BVH のテストアニメーションが適切に再生されるかテストをしておきます。

※ ここで上手くいかない場合、VRM > UniVRM-*** > Freeze T-Pose を実行してエラーが出ずにキャラクターが T ポーズになるかどうかを確認し、エラーが出る場合は解消します。
※ T ポーズ正規化はエラーがないかの確認のためであって、実際に書き出すのは Force T-Pose していない A ポーズのキャラクターです。

--

なお、自身で T ポーズを付けるワークフローにも対応しているので、その場合は Force T-Pose をオンにせず、Pose Freeze のみオンにして書き出します。

※ エクスポート時は Force T-Pose(必要な場合)と Pose Freeze をオンにする

書き出しに成功すれば、通常のワークフローで作成した VRM と同様にビューアーで表示することが出来ます。

※ T ポーズで腕が水平になっていれば問題ない

※ FBX-Linked VRM の場合、A ポーズのまま作業をしている性質上 T ポーズが問題ないかを特に注意して確認します。

おまけ: Unity エディター上での簡易プレビュー

上記の画像は VRM.SamplesSimpleViewer.unity をエディター上で実行して VRM ファイルを確認しているところですが、SimpleViewer.unity はビルドターゲットが非 Windows 環境になっているプロジェクトでの実行時に VRM ファイルを選択する事が出来ません。

※ Windows で Unity エディターを実行していても、ビルドターゲットがスマホになっている場合はファイルの選択が出来ません。

以下を参考にスクリプトを更新すると、ビルドターゲットがスマホだったり macOS だったりした場合でも任意の VRM ファイルを選択してプレビューできるようになります。

FileDialogForWindows.FileDialog がある部分に #elif UNITY_EDITOR... を追加。

#if UNITY_STANDALONE_WIN
   var path = FileDialogForWindows.FileDialog("open VRM", "vrm", "glb", "bvh");


// ↓ ↓ ↓ 追加 ↓ ↓ ↓
#elif UNITY_EDITOR
   var path = UnityEditor.EditorUtility.OpenFilePanel("Load VRM", "", "vrm");
// ↑ ↑ ↑ 追加 ↑ ↑ ↑


#else
   var path = Application.dataPath + "/default.vrm";
#endif

おまけ2: macOS / Linux での VRM ファイルのプレビュー

Windows 版のみ提供されている公式の VRM ビューアーは、表情の確認ができるなど UniVRM / VRM.Samples の SimpleViewer.unity よりも高機能なので、最終チェックには必須のアプリです。

macOS でも動作するようにアップデートしたアプリは以下からダウンロード出来ます。

VRM Spring Bone の作成

VRM 書き出しテストでボディーに問題が無ければ Spring Bone を追加して揺れものの設定をしてきます。

プレハブにコンポーネントを追加する際の注意点

ここからプレハブに対してコンポーネントを追加していくことになりますが、プレハブ由来の GameObject に対して直接コンポーネントを追加する、ということは控えます。
※ これは VRM データ作成に限らず、ですね。

プレハブ由来の GameObject に対して直接コンポーネントを追加すると、プレハブ更新でその GameObject がなくなった時にコンポーネントが消失してしまいます。

直接付与するのではなく、GameObject を追加してそこにコンポーネントを付与するようにしておけば、更新で GameObject がなくなったとしてもルートに吐き出されて残るので、それを使ってどうにかすることができます。

※ ルートもプレハブ由来ですが特別で、ほぼ確実に存在するのでコンポーネントを付与しても大丈夫です。
(ルートを作らないオプションもありますが、使っている人はいないでしょう。。。?)

※ 記事後半の Fbx 上書きテストで実際の挙動が確認できます。

--

揺れ物の設定は VRM エクスポーターが secondary ノードに纏めてくれるので、VRM 作成用シーンでは自分の扱いやすい状態で管理しても問題ありません。
secondary ノード自体、VRM 作成用シーンに残す必要はないようです。

ひとつの GameObject に同一コンポーネントを複数追加した状態だと、特定の VRM Spring Bone に対して Root Bone や Collider Group をスクリプトからアサイン、という事も難しくなるので、余程の事情が無い限りは Spring Bone コンポーネントひとつにつき GameObject をひとつ作って作業します。

※ Spring Bone 毎に GameObject を分けておいた方が管理・再利用がしやすい

VRM Spring Bone Collider Group の作成

続いてコライダーの追加もしていきます。

Unity シーンの構造的にはプレハブの階層に Collider を追加した状態になっていますが、特に問題なく VRM への書き出しが可能です。※ 上図ヒエラルキーウインドウ参照

※ コライダーを生成している様子

※ Spring Bone を設定した VRM ファイルをプレビュー表示

その他の VRM コンポーネントを設定

揺れものの設定が済んだら、その他の VRM コンポーネントの設定を行います。

VRM Look At Blend Shape Applier は忘れがちなので特に注意します。

  • VRM ルートノードにアサインされているべきコンポーネント一覧
    • VRM Meta
    • VRM Humanoid Description
    • Animator
    • VRM Blend Shape Proxy
    • VRM First Person
    • VRM Look At Head
    • VRM Look At Bone Applyer
      • または VRM Look At Blend Shape Applyer

各コンポーネントの詳細は、以下の公式サイトで確認できます。

各種アセットファイルの共用について

VRM Meta のアセットファイルは大した情報量ではないので、共用でも書き出しの度に確認・編集でも問題はなさそうです。

Blend Shape の設定ファイル群も同様に共用可能ですが、無用なトラブルを避ける為にはキャラクターそれぞれでユニークなものを使った方が良いでしょう。ファイル自体を複製しても参照先は複製元のファイルのままなので、ちょっと準備が面倒ではあります…。

書き出した VRM の構造

VRM コンポーネントの設定が済んだら、使用・配布が可能な最終 .vrm を書き出せる状態になっています。

書き出した最終 .vrm ファイルを Unity に読み戻すと、キャラクターは T ポーズになり Spring Bone コンポーネントはすべて secondary ノードに集約され、元々コンポーネントを持っていた SpringBone *** も残った状態になっています。

※ 書き出した FBX-Linked な .vrm を Unity に読み込んだ状態

通常のワークフローで作成した VRM と同様の .vrm を作成することが出来ました。

Fbx ファイル上書きテスト

最後に、いくつかのシチュエーションを想定した .fbx 差し替えテストをご紹介します。

メッシュ変更

後ろ髪の毛先はエクスポートミスですが、再エクスポートすれば良いだけなので気楽なものです。

※ 髪型チェンジ

メッシュの増減

肩に SD キャラを乗せました。

※ 肩パーツ追加

ウェイト更新

SD キャラたちは肩のボーンの影響を受けるだけでいいところ、腕のボーンの影響も受ける状態でエクスポートしてしまいました。

:sob::sob::sob:

UV 調整

微調整しない、なんてことはないですよね。

※ カットバイ対応・イベントバイ対応(?)も気軽に

ブレンドシェイプ追加

Maya から書き出すと blendShape1. ってノード名が接頭辞として付くようになっちゃって困っているんですが、どうしたらいいんでしょうか。

※ 洗顔後

階層構造の変更

Prefab 更新でペアレントが見つからなくなった GameObject は、Fbx ルートの直下に吐き出されます。
※ その後オリジナルの階層に戻したとしても、吐き出された GameObject は元には戻りません。

これは Unity でのアセット作成全般に言えることですが、GameObject を新規で追加してさえいれば後からどうにでもなるので、アセット由来で生成された GameObject に直接コンポーネントを追加するような事は、余程のことが無い限りは控えましょう。

※ 一度パブリッシュしたらタイポ修正を含めて変更はしないで欲しいですよね

おわりに

ここで紹介した手法は FBX の参照維持のため、意地になって結構むりくりやっている部分もあります。
とはいえ VRM 公式のエディタースクリプトへの対応が主ではあるので、書き出した VRM が変なことになっているという事はないと思います。

FBX-Linked VRM が仮に何か問題になるとしたら、

  • VRM ルートノードに付いてる Animator の Avatar まわり

    • 子供の Fbx ルートにも Animator を付けっぱなしで作業しているので、うまく行かなかったらエクスポート時に削除して書き出す、を試してみる
  • Blend Shape Clip の Relative Path まわり

    • Blend Shape Clip のインスペクタープレビューの仕様上、メッシュの相対パスの起点を Fbx ルート <=> VRM ルート間で切り替えている
    • エクスポート時は VRM ルートからの相対パスにする必要があり、その状態だと Inspector ではプレビュー・パラメーターが適切に表示されない(データ上は問題ない)
    • エディタースクリプトなのに表示のついでにデータ弄っちゃう系が v0.53 以降で追加されると、ノードを選択して Inspector が描画されるだけでデータが壊れる可能性はあるかも
      • Debug モードで Render Queue を弄って Normal モードの Inspector で表示すると勝手に元に戻るあれ

のあたりが怪しいです。

ともあれ、VRM を作っていて困ったときは FBX-Linked なこの手法に限らず、VRM > VRM-*** > Freeze T-Pose を実行してエラーが出ないかを確認し、あれば対処というイテレーションが解決の近道だと思います。

--

以上です。お疲れ様でした。

おまけ

VRM 初心者だったので、参照が切れた状態のシーンファイルであれこれしようとした結果、無駄な物をいくつか作ってしまいました。

「VRM Tool Kit リンク」
準備中

Skin Transfer

SkinnedMeshRenderer が参照しているボーンを、別のヒエラルキーにある同名のボーンに差し替えるツール

  • 用途: ボディーのスケルトン構造が共通で衣装が変わった時など。

VRM に限らず、

  • 体のボーンは共通で衣装が違う
  • アクセサリーを追加した
  • ウェイトを振り直した
  • 骨の位置を調整した
  • 揺れものの骨が追加・変更になった

等の場合に使える汎用的なツールです。

Mesh Asset Exporter

Skin Transfer を使っての衣装替えがうまくいったので調子に乗っていたらもっと単純な VRM 更新でエラーに遭遇してしまい、きっと Mesh がアセットファイルとして保存されていないからだろう、と作ってしまった物。

結果まったく関係ありませんでした。

※ VRM が ***.Meshes を書き出す理由は、シーンに参照だけ残すことで .unity ファイルのサイズ肥大化を防ぐため…??

各種ライセンス情報

この記事内で使用、改変しているモデルデータのライセンス情報です。

ユニティちゃん

この記事中で使用されているユニティちゃんは、ユニティちゃんライセンス条項の元に提供されています。

いつき / 制服

花咲うらら氏の公開されているモデルデータです。詳細は以下のリンク先で確認できます。

あわせてどうぞ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Unity] 2秒でオブジェクトプールしたい君へ [Lean Pool]

謝罪

2秒ではできません、ごめんなさい。

オブジェクトプールしたい

弾幕ゲーで弾Instantiateしてたら大変なことになったので、オブジェクトプールしたくなった。
簡単なオブジェクトプールくらいなら自分で書いてもそんなに時間はかからない気がするが、書きたくないのでアセットに頼りたい。

地獄。
image.png

Lean Pool を使って楽しよう

image.png
現在無料で一番人気のオブジェクトプールアセットである。

使いかた

ダウンロードしてインポートする。
プールしたいオブジェクトのInstantiateとDestroyを置換する。

Instantiate(poolShitaiObject); -> Lean.Pool.LeanPool.Spawn(poolShitaiObject);
Destroy(poolShitaiObject); -> Lean.Pool.LeanPool.Despawn(poolShitaiObject);

これだけでプールされるが、もう少しやることはある。

初期化

同じオブジェクトを使いまわす以上、以下のような普段やってる初期化は当てにならない。
AwakeとStartが都度呼ばれないのだ。

class Ahan : MonoBehaviour {
    public Ahahan ahahan;
    // 何もしてないので、再利用されるとき、値が引き継がれてしまう。
    public int ahanCount = 0;
    public int ahanAhanCount;

    private void Start() {
        ahahan = GetComponent<Ahahan>();
        // Startは一度は呼ばれるが、再利用時には呼び出されないので、値が引き継がれてしまう。
        ahanAhanCount = 10;
    }

    private void Update() {
        ahanCount++;
        ahanAhanCount++;
    }
}

変更される可能性のある値は全てOnEnableの中で初期化すべし。

class Ahan : MonoBehaviour {
    public Ahahan ahahan;
    public int ahanCount;
    public int ahanAhanCount;

    private void Start() {
        // 変化しない値はStartのままでいい。
        // 重たくない処理の場合は脳死で全部OnEnableにおいてもええで
        ahahan = GetComponent<Ahahan>();
    }

    // Spawn時に毎回呼び出されるため、値がリセットされる。
    private void OnEnable() {
        ahanCount = 0;
        ahanAhanCount = 10;
    }

    private void Update() {
        ahanCount++;
        ahanAhanCount++;
    }
}

OnEnableはStartの完全な代替にはなれない

なぜならStartはInstantiateされた次のフレームに実行されるが、OnEnableはSpawnされた時点で実行されるからだ。
どういうことかというと、
Instantiate -> 変数にいろいろ代入 -> 次のフレームにStartが実行されて、代入された値をもとに準備ができる
がStartは出来るのに対して、OnEnableは、
Spawn -> OnEnableがその瞬間実行される -> 変数にいろいろ代入 -> OnEnableはもう実行済みのため、次のフレームでは実行されず、値が反映されない
という感じになる。
普通に使っている分には脳死でStart -> OnEnableで問題ないはず。

プールサイズを設定する

ただInstantiateとDestroyを置き換えただけでも高速化はされる。
しかしプールサイズが設定されていないため、弾が増える最初のタイミングはやはり重い。

こんな感じ。
image.png

最初から使いまわす用のインスタンスを用意しておくと、このコストもなくなる。
プールオブジェクトを作る。
image.png

image.png
Prefabのところに弾のPrefabを置いて、Preloadに用意したい弾の数を入れる(適当に1000)。

こうなった。
image.png

比較してみる

Before
image.png
After
image.png

これで君もニッコリ

やったね!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む