はじめに
この記事はVTuber Tech #1 Advent Calendar 2018の1日目の記事です。
こんにちは、@nkjzmです。
今回はUnityとLive2Dを使ったVTuber配信システムの作り方を紹介します。
Unityに初めて触る人でも分かるくらい丁寧に書いているので、ぜひ色々な方にご覧いただきたいです。
現状、Live2DでのVTuber配信はFaceRigというアプリケーションが用いられることが多いと思います。導入すればすぐにモデルを動かすことができるため非常に便利なのですが、反面キャラクターとしての表現を追求する際に制約となる場合もあります。
そこで、本記事ではUnityを用いることで拡張しやすいVTuber配信システムの作り方を紹介します。
サンプルとして完成プロジェクトも用意しましたので、適宜参考にしながら読み進めてください。
この記事で扱うこと
- UnityとLive2Dを使ったシステム構築
- OBSを使った配信方法
この記事で扱わないこと
- Live2Dモデルの作り方
必要な環境
- 以下のいずれかのOS
- macOS High Sierra (10.13.6にて動作確認済み)
- Windows 10
-
Unity
- 2017.4.x~ / 2018.2.x~ (2018.2.11f1にて動作確認済み)
- Live2D Cubism 3 SDK for Unity
-
OVRLipSync
- 1.28.0にて動作確認済み
VTuberKitについて
nkjzm/VTuberKit
https://github.com/nkjzm/VTuberKit
今回紹介する方法の完成プロジェクトです。
主にAssets/VTuberKit/Examples/Koharu/
以下のシーンが参考になると思います。
MITライセンスで配布しているので、このプロジェクトを基盤にシステムを作っていただいても大丈夫です。
※ただしいくつかのSDKの利用を前提としているため、それぞれのライセンスには従ってください。
特にLive2Dの「拡張性アプリケーション」に該当しないかどうかはきちんと確認してください。
拡張性アプリケーションのリリースライセンスについて
利用方法についてはリポジトリのREADME.mdをご覧ください。
質問について
記事中で分からないことがあれば@nkjzmまでご連絡ください(軽い質問であればお答えします)。また、月額制のメンターサービスで開発サポートをしているので、詳しく教えてほしい方はこちらをご利用ください。
https://menta.work/plan/1115
配信システム基盤の作成
ここからはVTuber配信システムの具体的な作成手順を紹介します。
分からない点があれば、適宜VTuberKitを参考にしてください。
Unityプロジェクトの新規作成
Unityのインストールが済んでいない方は、こちらからインストーラーをダウンロードします。UnityHubを利用すると複数バージョンのUnityを管理出来るのでオススメです。
具体的な手順は今回は割愛します。画面に従ってインストールを進めてください。
UnityHub(もしくはUnity)を起動します。

右上の「新規」をクリックしてください。

- Project Nameを入力
- Templeteを
2D
に変更
上記のように入力して「Create project」をクリックしてください。

プロジェクトが作成され、Unityエディタと呼ばれる画面が開くと思います。
Live2DモデルをUnityに組み込み
ここからは実際にLive2DのモデルをUnity上に組み込んで行きましょう。
Live2D SDKのインポート
UnityでLive2Dを扱うためのSDKをインポートします。
配布ページにアクセスすると、利用にあたってのライセンスが表示されます。ライセンスに同意した上で、少し下の方にある「Download Live2D Cubism 3 SDK for Unity R10」のリンクをクリックしてください。ダウンロードが開始します。

次に、ダウンロードしたCubism3SDKforUnity-9.unitypackage
というファイルをダブルクリックしてください。

このような画面が開くと思います。
(上記の操作で画面が開かない場合は、Unityエディタ上にドラッグアンドドロップする操作を試してみてください。)
すべてチェックマークが入っていることを確認して、右下のインポートボタンを押してください。

このように再起動を促すメッセージが表示されるので、「ok」をクリックします。インポート終了後に再起動をしてください。
再起動の手順としては、まずUnityを終了させます。Unityを選択した状態で、MacならCommand(⌘) + Q
を、WindowsならAlt + F4
を押してください。
次にUnityHubアプリを起動し、プロジェクトの中から先程作成したプロジェクトを選択してください。

これでLive2D SDKが読み込みは完了です。
では正常に読み込めているか確認してみましょう。SDKにはいくつかのサンプルが含まれています。その中の一つを開いてみたいと思います。

①Unityエディタ上のProjectビューから、[Asset]>[Live2D]>[Cubism]>[Samples]>[Animation]
と辿っていき、②Animation
というシーンファイルをダブルクリックしてください。③Gameビューにキャラクターが表示されます。④最後に再生ボタンを押してください。
Gameビューのキャラクターがこのようにアニメーションしていることが確認できると思います。
モデルのインポート
他のモデルをインポートする手順を紹介します。
今回は公式の『桃瀬ひより』というサンプルモデルを例に説明します。
自作モデルを利用する場合などは、適宜読み替えて進めてください。
サンプルモデル集より『桃瀬ひより』の「Freeダウンロード」をクリックしてください。利用の際には『無償提供マテリアルの使用許諾契約書』を確認しておいてください。

zipファイルがダウンロード出来るので、ダブルクリックなどで解凍しておいてください。
Live2D Cubism 3のモデルデータは.cmo3
という拡張子で保存されています。しかし、Unityにインポートする際には.moc3
という拡張子の組込み用ファイル形式を用意する必要があります。
今回利用する『桃瀬ひより』は.cmo3
形式のみの配布なので、.moc3
形式に書き出す方法を説明します。
組込み用ファイルの書き出しにはCubism Editorを使用します。
こちらからCubism Editorをインストールしましょう。

利用規約に同意した後、メールアドレスを入力し「最新版をダウンロード」をクリックしてください。ダウンロードしたファイルをダブルクリックし、手順に従ってインストールしてください。

インストールが完了しました。
次に、以下のページに従って.moc3
ファイルを書き出してください。
moc3ファイルの書き出し | Live2D Manuals & Tutorials
http://docs.live2d.com/cubism-editor-manual/moc3-file/
(2020.07.27追記)上記URLがリンク切れになっていました。恐らく以下の手順で大丈夫ですが、未確認です。
組み込み用データ | Live2D Manuals & Tutorials
https://docs.live2d.com/cubism-editor-manual/export-moc3-motion3-files/

書き出したファイルは、上記のように一つのフォルダにまとめておいてください。
組込み用ファイルをUnityにインポートしていきます。先程のフォルダをUnityエディタのProjectビュー上にドラッグアンドドロップします。

インポートが終わると、このようにプレハブファイルが生成されます。
プレハブファイルが正常に生成されない時は?
- Live2D SDKのインポート後にUnityの再起動はしましたか?
- 書き出し用ファイルに不足はありませんか?
モデルをシーン上に配置する
インポートしたモデルをUnityで表示してみましょう。
Projectビュー上で右クリックをして、[Create]>[Scene]
を選択してください。

Main
と入力してください。

作成したシーンをダブルクリックで開いてください。
もし以下のようなウィンドウが表示されたら、[Don't Save]
を押せば大丈夫です。
Projectビューから、生成されたプレハブを選択し、Hierarchyビューにドラッグアンドドロップします。

以下のような状態になればOKです。

Sceneビューにはモデルが表示されていますが、Gameビューには小さく表示されてしまっています。カメラの設定を変更して、大きく表示されるように調整をします。
HierarchyビューでMain Camera
を選択してください。
Inspectorビューにカメラの設定が表示されるので、以下のように変更してください。

- TransformのPosition yを
0.4
に変更 - Backgroundを
(R,G,B)=(0,255,0)
に変更 - CameraのProjectionが
Orthographic
になっていることを確認する - Sizeを
0.2
に変更


Gameビューにこのように表示されるようになりました。
メニューから[File]>[Save Scenes]
をクリックして、シーンを保存しておきましょう。

では最後に、Unity上でモデルを動かしてみましょう。
Hierarchyビューからモデルを選択してみてください。
(レイアウトを変えています)
InspectorビューにCubism Parameters Inspecotr (Script)
というコンポーネントが表示されると思います。それぞれの項目がモデルの各パラメータと対応しています。自由に色々と動かしてみましょう。
このように連動してモデルが動くことが確認できます。
なお、変更したパラメータは、右下の「Reset」ボタンでリセットすることができます。
プレゼンスを上げる
さて、ここからはLive2Dモデルがキャラクターらしく振る舞うための設定をしていきます。
口パクの実装
まずは自分の声に合わせてキャラクターが口パクをするようにしてみましょう。
Unityでマイク音声を取得し、音声の大きさをキャラクターの口の開閉に反映させることで実現させます。
Projectビュー上で右クリックをして、[Create]>[C# Script]
をクリックしてください。ファイル名にはSimpleLipSyncer
と入力してください。
SimpleLipSyncer
をダブルクリックしてエディタを開きます。以下のスクリプトをコピーアンドペーストし、保存してください。
using UnityEngine;
using Live2D.Cubism.Core;
/// <summary>
/// 口パクを行うクラス
/// </summary>
[RequireComponent(typeof(AudioSource))]
public class SimpleLipSyncer : MonoBehaviour
{
AudioSource audioSource = null;
[SerializeField]
CubismParameter MouthOpenParameter = null;
float velocity = 0.0f;
float currentVolume = 0.0f;
[SerializeField]
float Power = 20f;
[SerializeField, Range(0f, 1f)]
float Threshold = 0.1f;
void Start()
{
// 空の Audio Sourceを取得
audioSource = GetComponent<AudioSource>();
// Audio Source の Audio Clip をマイク入力に設定
// 引数は、デバイス名(null ならデフォルト)、ループ、何秒取るか、サンプリング周波数
audioSource.clip = Microphone.Start(null, true, 1, 44100);
// マイクが Ready になるまで待機(一瞬)
while (Microphone.GetPosition(null) <= 0) { }
// 再生開始(録った先から再生、スピーカーから出力するとハウリングします)
audioSource.Play();
audioSource.loop = true;
}
private void LateUpdate()
{
float targetVolume = GetAveragedVolume() * Power;
targetVolume = targetVolume < Threshold ? 0 : targetVolume;
currentVolume = Mathf.SmoothDamp(currentVolume, targetVolume, ref velocity, 0.05f);
if (MouthOpenParameter == null)
{
Debug.LogError("MouthOpenParameterが設定されていません");
return;
}
// CubismParameterの更新はLateUpdate()内で行う必要がある点に注意
MouthOpenParameter.Value = Mathf.Clamp01(currentVolume);
}
float GetAveragedVolume()
{
float[] data = new float[256];
float a = 0;
audioSource.GetOutputData(data, 0);
foreach (float s in data)
{
a += Mathf.Abs(s);
}
return a / 255.0f;
}
}
Hierarchyビュー上で右クリックをして、Create Empty
を選択してください。作成したGameObjectを選択した状態で、Add Component
をクリックしてください。
SimpleLipSyncを検索し、決定します。

このスクリプトがマイク音声を取得する役割を果たします。
次に取得した音声を口の開閉に反映させるための設定を行います。
先程のGameObjectを選択した状態で、Simple Lip Syncer
のMouth Open Parameter
の右端の○をクリックします。ウィンドウが表示されるので、ParameterMouthOpenY
を検索して選択します。

この状態でPlayボタンを押して再生し、してマイクに向かって喋ってみましょう。
キャラクターが自分の声に合わせて口パクするようになりました。
なお、この方法だとマイク音がPCから鳴ってしまう点に注意してください。
(問題がある場合は、後述のAniLipSync-live2dなどを使用してください。口の形が一つだけでも5箇所に設定してしまって大丈夫です。)
まばたきを付ける
参考: 自動まばたきの設定
シーン上のモデルに以下のスクリプトをAddComponent
します。
-
CubismEyeBlinkController
-
BlendMode
をOverride
に設定
-
CubismAutoEyeBlinkInput

まばたきさせたいパラメータ(=目の開閉パラメータ)にCubismEyeBlinkParameter
をAddComponent
します。
対象は以下の2つです。
モデル/Parameters/ParamEyeLOpen
モデル/Parameters/ParamEyeROpen

設定後、再生してみるとまばたきすることが確認できると思います。
呼吸モーション
シーン上のモデルに以下のスクリプトをAddComponent
します。
-
CubismHarmonicMotionController
-
BlendMode
をOverride
に設定
-
呼吸に合わせて動かしたいパラメータにCubismHarmonicMotionParameter
をAddComponent
します。
今回は以下の2つに追加してみましょう。
モデル/Parameters/ParamBodyAngleY
モデル/Parameters/ParamBreath

設定後、再生してみると呼吸モーションを確認できると思います。
頭と視線を動かす
マウスの動きに合わせてキャラクターが目で追うようにしてみましょう。
Projectビュー上で右クリックをして、[Create]>[C# Script]
をクリックしてください。ファイル名にはGazeController
と入力してください。
GazeController
をダブルクリックしてエディタを開きます。以下のスクリプトをコピーアンドペーストし、保存してください。
using Live2D.Cubism.Core;
using UnityEngine;
/// <summary>
/// 目線の追従を行うクラス
/// </summary>
public class GazeController : MonoBehaviour
{
[SerializeField]
Transform Anchor = null;
Vector3 centerOnScreen;
void Start()
{
centerOnScreen = Camera.main.WorldToScreenPoint(Anchor.position);
}
void LateUpdate()
{
var mousePos = Input.mousePosition - centerOnScreen;
UpdateRotate(new Vector3(mousePos.x, mousePos.y, 0) * 0.2f);
}
Vector3 currentRotateion = Vector3.zero;
Vector3 eulerVelocity = Vector3.zero;
[SerializeField]
CubismParameter HeadAngleX = null, HeadAngleY = null, HeadAngleZ = null;
[SerializeField]
CubismParameter EyeBallX = null, EyeBallY = null;
[SerializeField]
float EaseTime = 0.2f;
[SerializeField]
float EyeBallXRate = 0.05f;
[SerializeField]
float EyeBallYRate = 0.02f;
[SerializeField]
bool ReversedGazing = false;
void UpdateRotate(Vector3 targetEulerAngle)
{
currentRotateion = Vector3.SmoothDamp(currentRotateion, targetEulerAngle, ref eulerVelocity, EaseTime);
// 頭の角度
SetParameter(HeadAngleX, currentRotateion.x);
SetParameter(HeadAngleY, currentRotateion.y);
SetParameter(HeadAngleZ, currentRotateion.z);
// 眼球の向き
SetParameter(EyeBallX, currentRotateion.x * EyeBallXRate * (ReversedGazing ? -1 : 1));
SetParameter(EyeBallY, currentRotateion.y * EyeBallYRate * (ReversedGazing ? -1 : 1));
}
void SetParameter(CubismParameter parameter, float value)
{
if (parameter != null)
{
parameter.Value = Mathf.Clamp(value, parameter.MinimumValue, parameter.MaximumValue);
}
}
}
Hierarchyビューのモデルの上で右クリックをし、[CreateEmpty]
を選択、Anchor
という名前にしてください。Editorビュー上で眉間の位置にAnchor
を移動させましょう。ひよりモデルの場合は、(x,y,z)=(0,0.45,0)
の位置です。

モデルに対して先程のコンポーネントをアタッチします。
以下のように設定してください。対応するパラメータが存在しない場合があるかと思いますが、ある分だけで大丈夫です。

この状態で再生をし、マウスを動かして見てください。
マウスの先を追うように頭が動くと思います。

また、ReversedGazing
にチェックを入れてみると以下のようになります。
今度は常に正面を見つめた状態で頭が動くようになりました。
表情を付ける
こちらの記事を参考にしてください。
表情・ポーズを切り替える
応用編
ここからは応用編です。いくつかの「より魅力的になる表現」を紹介するので、ぜひ参考にしてみてください。
リミテッドアニメのようなリップシンクを実装する
Live2Dでアニメ調のリップシンクを実現できるAniLipSync-live2dというライブラリを使った例です。
「あーいーうーえーおー。こんな感じで、リップシンクができます!」
別の記事で導入方法を紹介しているので、参考にしてみてください。
Live2Dでアニメ調のリップシンクを実現する『AniLipSync-live2d』の使い方
ボイスチェンジャー
VTuberとして活動するとき、見た目と声が合っていない場合があると思います。
その場合はボイスチェンジャーを使ってリアルタイムに別の声に変換するという選択肢があります。
Windowsではフリーソフトの恋声を使ったやり方がお手軽です。MacならGarageBandで代替出来ると思います。
また、VT-4などボイストランスフォーマーと呼ばれる機器を用いて声の変換を行うこともあります。是非調べてみてください。
あっまじだ、隠すと全然違う…知見だ… pic.twitter.com/JKK0Je8kds
— Nakaji Kohki (@kohki_nakaji) 2018年7月14日
ARKitを使った表情認識
iPhone X以降のFaceIDが付いた端末で利用できるARKitのFace Trackingという機能を使うと、このように高い精度で顔認識をして表情などを変えることが出来ます。
iPhone X+ARKit+Live2Dがどんな感じに動くかのサンプル
— 🕯 (@mzyy94) 2017年11月16日
(音声はPCで再生してるやつを録音したもの)
まだ表情のパラメーターは弄りがいがある感じ pic.twitter.com/xNQZcQhsTY
OpenCVforUnityを使った実装
ARKitのFace Trackingを使わない顔認識だと、このような選択肢もあります。
少し高額な有料アセットが必要ですが、導入しやすいと思います。
参考: FaceRig無しでも中の人(二次元)になりたい!【Unity × OpenCV × Dlib × Live2D】 - Qiita
OBSを使った動画の収録・配信
キャラクターを動かすための配信システムは最低限できたと思うので、次は実際に配信する手順を紹介します。
配信アプリの書き出し
まずは先程のシステムを、配信に使いやすいようにアプリとして書き出します。
PlayerSettingsの設定
メニューより、[Edit]>[Project Settings]>[Player]
を選択します。

Inscpectビューで[スタンドアロンタブ]>[Resolution and Presentation]
を開き、Run In Background
にチェックをいれる。

BuildSettingsの設定
メニューより、[File]>[Build Settings]
を選択します。

Add Open Scenes
を選択し、MainシーンがScenes In Build
に追加されたことを確認してBuildボタンを押す。

適当な名前を付けて「Save」ボタンを押す。

このように無事アプリが書き出されたらビルド成功です。
Windowsの方は適宜読み替えてください。

.dll
周りでエラーが出た場合、Unityを再起動してもう一度試してみてください。
アプリの起動確認
ビルドしたファイルをダブルクリックで実行します。

Windowed
にチェックを入れます。
その他の設定はおまかせで良いですが、Live2DやOVRLipSyncはそこそこ負荷が高いアプリなので、動作が重くなるようでしたら低めにすると良いかと思います。
任意の設定が完了したら「Play!」ボタンを押します。

モデルが呼吸などのアニメーションをしていること、リップシンクが正常に動くことなどを確認してください。
OBSの設定
配信にはOpen Broadcaster Software (OBS)というアプリケーションを利用します。
Windows, Mac, Linuxをサポートしているオープンソースの配信ソフトウェアです。
こちらのダウンロードページを開き、お使いのOSに対応したインストーラーをダウンロードしてください。また、そのままインストールを進めてください。
インストールが完了したらOBSを起動します。初回起動時におすすめ設定を適用するか聞かれるかもしれませんが、あとから変更できるのでどちらでも大丈夫です。

このような画面が表示されます。
ソースの設定
ソースの「+」からウィンドウキャプチャを選択

新規作成が選択された状態で任意の名前を入力し、OKを押します。名前はそのままでも大丈夫です。

リストの中から書き出したアプリを選択する。
起動中のアプリのみがリストに表示される点に注意してください。

正しく選択できると上記のように書き出したアプリの映像が表示されるので、その状態でOKを押します。
ソースから、先程追加したウィンドウキャプチャの上で右クリックをし、フィルタ
を選択します。

エフェクトフィルタよりクロマキー
を選択

デフォルトで緑になっているので、このように背景が透過されます。
もしUnity側で別の色を背景色に設定していた場合などは、適宜設定を変更してください。

(Macのみ)ウィンドウの枠を切り抜きます。エフェクトフィルタよりクロップ/パッド
を選択してください。画像のように値を調整してください。

設定が完了したら、右下の「閉じる」ボタンを押してください。
最後に、赤枠をドラッグしてサイズと位置を調整してください。
端の方は補正が効くので合わせやすいと思います。
背景の設定
背景を設定します。今回は画像を利用しますが、例えば動画ファイルやデスクトップ、ゲーム画面などを背景にしても大丈夫です。著作権などには十分に注意してください。
今回はこちらの画像を使用させていただきました。
ソースの「+」から画像を選択し、新規作成から任意の名前を付けてOKを押します。
「参照」をクリックし、ファイラーから任意の画像を選択します。

上記のようになったら、「OK」をクリックします。
赤枠をドラッグしてサイズや位置の調整を行います。
背景がキャラクターよりも上に表示されているので、重なり順を入れ替えます。
ソースから画像をクリックして、「V」をクリックします。

ソースでは順番が上のものほど手前に表示されるので、以下のように正しい重なり順になりました。

これで映像の準備は完了しました。
音声の設定
最後に音声の設定をします。
ソースの「+」から「音声入力キャプチャ」を選択し、新規作成から任意の名前を打ってOKを押します。
デバイスのリストから「既定」を選択します。もし入力したい音声ソースがある場合や、ボイスチェンジャーなどを使っていて仮想音声ソース(Soundflower等)を使いたい場合などは、そちらを設定してください。

選択したらOKを押します。
設定した音声に併せてゲージが反応することが確認出来ると思います。
これだけでも良いのですが、OBSでは映像のキャプチャ時に少し遅延があります。
書き出したアプリをOBSを並べて口パクさせてみると、元アプリ(右)の口が動いてからOBS(左)の口が動くまでにワンテンポ遅れていることが分かると思います。
そこで、ボイスの収録を映像の遅延に併せて少し遅らせる設定をします。
ミキサーの右の歯車アイコンをクリックし、「オーディオの詳細プロパティ」を選択してください。

マイクの同期オフセットに値を入力してください。環境毎に遅延時間が異なるので、調整してみてください。

完了したら閉じるを押してください。
これで映像と音声の準備が出来ました。
動画の録画
右下の「設定」より、出力タブの「録画フォーマット」をmp4やmovなどに変更してください。
(デフォルトのflv
だと扱いづらいと思うので)
録画開始ボタンで録画開始、録画終了ボタンで録画終了です。
なお、リップシンクの反応が悪い時は、書き出したアプリを選択した状態で収録を行ってください(録画開始ボタンを押した直後に、書き出したアプリのウィンドウをクリックすればOKです)。ウィンドウを選択していない状態だと認識しづらい問題があるようです。
録画が終了すると、MacだとMovieフォルダなどに出力されます。
出力場所は、「設定」から出力タブを選び、「録画ファイルのパス」にて確認・変更することが出来ます。

動画を再生し、映像や音声がきちんと収録されていることを確認してください。
あとはTwitterやYouTubeにアップロードすれば、見事VTuberデビューです!
その他
OBSにはYouTubeなどの生配信を行う機能や、音声のノイズを除去する機能など、様々な機能が付いています。
やりたいことがあれば、是非調べて挑戦してみてください。
最後に
今回扱った内容は基本的なことばかりです。
色々な技術を組み合わせてぜひ魅力的なキャラクターを生み出してください!
明日は、バーチャルモーションキャプチャ開発者の @sh_akira さんによるUniVRM+SteamVR+Final IKで始めるVTuberです。
VTuber Tech #1 Advent Calendar 2018
VTuber Tech #2 Advent Calendar 2018
関連
【サポーターズCoLab勉強会】Unity+Live2Dで始めるVTuber入門ハンズオン - サポーターズCoLab
https://supporterzcolab.com/event/568/
低スペックPCでVtuberになるいくつかの方法 - Qiita
https://qiita.com/Hirosaji/items/83777124823683766d96