見出し画像

ドット絵VTuberシステムを作る

hako 生活さんがフェイシャルトラッキングでドット絵を動かすやつをやっていて、楽しそうだったので自分も作ってみました。

Xで結構たくさんの反応があったのもあり、せっかくなので今回作ったシステムでどんなことをやってるかを軽く紹介してみます。
チュートリアル記事ではないので再現性はあまり無いですが、何かヒントになればということで……。もしあなたがドット絵スタイルのアバター制作にチャレンジしていて、この記事でわからないことがあればXでお聞きください。可能な範囲でお答えしたいです!

環境

  • Unity 2023.2.3f1

主要なパッケージはこんな感じ↓

  • 2D Animation 10.0.3

  • 2D Aseprite Importer 1.0.1

  • 2D PSD Importer 9.0.1

  • Burst 1.8.11

  • Live Capture 4.0.0

  • Universal RP 16.0.4

方針

フェイシャルキャプチャ

Unity Live Captureを使いました。

Unity Live CaptureはiOSデバイス (ARKit) のフェイシャルキャプチャデータをリアルタイムでUnityに持ち込む機能があります。エディタ専用なのがちょっと難点ですが、まあ公開アプリを作るわけではないのでその点は問題なし。

Unityでのフェイシャルキャプチャのソリューションとしては、数年前にDlib FaceLandmark Detectorを使ったことがありましたが、Unity Live Captureのほうが簡単に感じました。Dlib FaceLandmark Detectorのほうはカメラさえあれば動かせますし、公開アプリを作るのには向いてそうです。

アニメーション・レンダリング

VTuberといえば、Live2D等による変形や回転を使ったアニメーションがつきもの。しかしドット絵は連続的な回転や変形とは相性があまりよくありません。手で打ったドットの雰囲気が回転や変形によって失われてしまいます。

回転と変形を封じてシステムを構築することもできますが、モデルの表現力はそのぶん犠牲になります。ここはバランスでしかないのですが、ひとまずは回転や変形も使ってやってみることにしました。

ということで、回転や変形もさせつつ、最終的には低解像度(256x256)にピクセル化して出力します。これも好みですが、ドット絵を回転・変形させてもなお、ピクセルパーフェクトだけは譲れない……!

工程

デザイン

まずはAsepriteでレイヤーを分けつつドット絵を清書します。

インポート

Aseprite Importerを使って直接インポートします。勝手にレイヤーごとにスプライトをスライスしてくれるので、今回のような用途にもぴったり。

首を動かす

ひとまずは最も簡単そうな首を動かすアニメーションから着手しました。
Unity Live Captureは頭の姿勢をQuaternionで受け取ることができます。Neckみたいな空のTransformを作成し、それに姿勢を反映させます。
次に、Neck姿勢への各パーツ追従ですが、普通にNeckの子Transformとして各パーツを配置することはせず、Parent Constraintコンポーネントを使いました。理由は二つあります。

ひとつめは、Aseprite ImporterでインポートしたPrefabに破壊的な変更を加えたくなかったからです。破壊的変更は、もとのaseファイルの変更がすぐにPrefabに反映されるAseprite Importerの利点をつぶすことになります。

ふたつめは、Z軸回転のみを反映させたかったからです。Parent Constraintは追従する回転軸や座標軸を限定させることができます。2D素材をX軸やY軸に沿って回転させると違和感が大きく、今回はZ軸回転のみを追従させるようにしました。

Parent Constraintによる恩恵はもうひとつあります。今回のモデルでは目や眉、口の姿勢を固定しています。首の回転に各パーツは追従しますが、パーツ自体は元の姿勢を維持するということです。先ほどドット絵と回転の相性が悪いという話をしましたが、なかでも目や口は表情の印象を大きく左右する要素なので、もとのドット感を維持するようにしました。
デメリットとして、大きく首を動かすと表情感が変わる(たれ目、つり目風になる)問題がありますが、ここはドット感の維持を優先することにしました。

顔を傾けても目や口の角度が維持される

ということで、首が動いただけですが、これだけでもかなりモチベーションがわきました。

未知の問題に取り組むときは、やはりlow-hanging fruit(簡単かつ見返りの大きい目標)から始めるのがよい……。超余談ですが、low-hanging fruitという言葉は下のKeijiroさんの記事で知りました。この記事、新しい課題に取り組むプロセスの見本として(専門的な技術を抜きにして読んでも)素晴らしく、私も定期的に読み返すくらい好きな記事なんですよね。おすすめです。

髪を動かす・変形編

髪を動かすには、変形方法物理挙動の2点を考える必要があります。

変形方法としては2D Animationパッケージを採用しました。これはあまりほかの手法を検討してないのですが、以前使ったことがあり大体使い方がわかっていて安心感があったのが選定の理由です。
2D Animationパッケージはスプライトに対するスキニングとスケルタルアニメーションを行うことができます。

スキニング設定画面

2D AnimationにおけるスキニングのワークフローはPSD Importerと連携できるようになっています。PSB (注:PSDではない) をインポートすると、レイヤーを分けた素材を自動でスライスさせつつ、スキニング設定時には各レイヤーの素材を元の位置関係に直した状態で作業することができます。これがとっても便利。
PSBの作成には手元にあったsai2を使いました(Photoshopのサブスクリプションがなかったので……)。sai2がPSBも扱えることを初めて知りました。
髪に関しては元のドット絵の8倍の解像度で作っています。これはどうせ回転・変形させるなら、高解像度で素材を作ってレンダリング時にピクセル化したほうが輪郭がきれいに出るだろうと思ったからです。

髪を動かす・物理挙動編

物理挙動は自作(!)でがんばりました。3Dキャラモデルの揺れものやクロスシミュレーションで使われる、いわゆるSpring Boneのアセット類はいくつかありますが、メジャーなものはどれも3D用なんですよね……。となると選択肢はUnity標準のジョイントを繋げて作る3DのSpringBone系の処理結果を2Dに転写する自作のどれかになります。

最近こうしたヒモや布の物理挙動を実現するアルゴリズムとしてPosition Based Dynamics (PBD) というものがあるのを知り、いくつかの実装例を記事で見かけていて興味がわいていました。自作を選んだのはこれが理由として大きいです。

あらゆる場面において、大抵『自作』は目的を達成するための合理的な選択ではないことが多いですが、こういうところで車輪の再発明を積極的に行ってきたのが自分の筋肉となっている実感があるので、今回も興味ドリブンでやってみることにしました。

PBDの実装にあたって特に参考にさせていただいた記事です👉

ただ、ヒモの曲がり具合をコントロールする曲げ拘束 (Bending Constraint) に関する情報は検索してもほとんど見つからず、結局はPBDの元の論文と格闘することになりました。今回のシステムは全体を通してここが一番大変でしたが、ずっと気になっていたPBDについて理解が深まったので満足しました。

2Dでの実装例はまだなさそうだったので、専門家向けにとりあえずソースコードを貼っておきます。

https://gist.github.com/ruccho/6526987988fdd1f3cdc4fd0c69ce8964

これもちゃんと使いやすいように体裁を整えてどこかで公開したいですね。

ということで髪の物理挙動もでき、首の動きによって髪がなびく動きが得られました。シミュレーション系のアルゴリズムを実装してうまく動いた時の喜びってやっぱり大きい……。技術的に最も困難なポイントはこれでパスでき、あとは大体順当に実装できる見込みがあったので、この段階ではもう安心していました。

表情をつける

Unity Live Captureでは、ARKitの表情データがそのまま取得できます。

こちらの記事で紹介されているように、表情データはさまざまな特徴量を0~1の数値で取得することができます。たとえば左目の開き具合であればeyeBlinkLeftの値に応じて表示する画像を切り替える……というように、かなりシンプルな処理の組み合わせで実現できます。

目に関しては簡単だったのですが、口は少し難しかったです。ARKitの口関係の特徴量は33種類と、その豊富さには目を見張るものがあり、いくらでも凝りようがありそうでした。

最終的には、口のアニメーションはパラメータによる素材の切り替えで実現したのですが、パラメータの処理方法を少し工夫しました。具体的には、あらかじめ口の各素材におけるモデルポーズを設定しておき、モデルポーズと最も類似している素材を選択する、という方法をとりました。モデルポーズとの類似度は、n種類の特徴量のセットをn次元のベクトルとみなして距離を計算することによって求めました。多クラス分類問題としてはもっと工夫のし甲斐もありそうですが、このくらいの素朴な実装でも思いのほか自然な挙動が得られたので、これでよしとすることにしました。

この方法は、口の表現力を高めようと思ったときに、新たに口の素材を描いてモデルポーズさえ設定すれば作業が終わるという利点があります。

各素材におけるモデルポーズ

展望

冬休みの時間を活用して趣味開発に没頭できて楽しかったです。ただ特に配信活動を行う予定がないので、VTuberシステムとしては日の目を見なさそうですが……。たとえばゲームにおけるリッチなキャラクターグラフィック表現として今回のシステムを組み込んでみるのはアリかもしれません。

この冬休みの裏テーマとして、回転や変形に強いドット絵描画システムを作るという野望があり、今回のシステムづくりのついでにやってみたかったのですが、今回は実現せずでした。アイデアとしては数年来温めているのがあるのですが実装難度が高く……。またタイミングを見てチャレンジしたいです。

この記事が気に入ったらサポートをしてみませんか?