各Cubism SDKの比較

最終更新: 2023年1月26日

  Cubism SDK for Unity Cubism SDK for Native Cubism SDK for Web Cubism SDK for Java
マスクの共有 CubismMaskControllerで指定したMaskTextureを共有 モデル内だけで共有したマスクテクスチャを使用 同左 同左
マスクの枚数 デフォルトで64枚のマスクが可能 デフォルトで36枚のマスクが可能
※高精細マスクを有効化することで制限を解除可能。
詳細は『マスクの前処理方式(Native)』を参照
デフォルトで36枚のマスクが可能 デフォルトで36枚のマスクが可能
※高精細マスクを有効化することで制限を解除可能。
詳細は『マスクの前処理方式(Java)』を参照
マスクの取り方 マスクサイズは固定
マスクをかける側を内包できる正方形で構成する
自動的なリサイズ
マスクをかけられる側を内包できる矩形で
マスク形状にいっぱいに構成する
同左 同左
描画の方法 描画順(昇順降順)、Z値(昇順降順) 描画順昇順のみ 同左 同左
OWポーズ機能 あり(R11 beta1~) あり 同左 同左
OW表情機能 あり(R11 beta1~) あり 同左 同左
モーション管理 Unityのmotion3.jsonをAnimationClipに変換し、
Mecanimで行う
Cubism SDK for Nativeで行う Cubism SDK for Webで行う Cubism SDK for Javaで行う
SDK使用言語 C# C++ Type Script Java
Live2D配置 GUI上 コード上 同左 同左
出力先プラットフォーム Windows, macOS, iOS, Android, WebGL,
PlayStation 4, Nintendo Switch
Windows, macOS, Linux, iOS, Android,
PlayStation 4, Nintendo Switch
Webブラウザ Android

マスク特性の違い

Cubism SDK for Unity

Unityではマスク画像の共有はCubismMaskControllerで指定されるMaskTexture単位で共有されます。
MaskTextureは複数作成することが可能で、同種のモデルであってもMaskTextureの指定が違えば別々に使用されます。
単一のモデルの中で複数のMaskTextureを使用することはできません。

テクスチャ一枚あたりのマスクの取り扱い枚数はMaskTextureのSubdivisionsの項目を変えることで変更することができます。
Subdivisionsの値は軸ごとのマスク取り扱い数で、以下の表のように取り扱い数が変化します。

Subdivisions
マスク枚数16642561024

標準ではマスクの取り扱い枚数に合わせてSubdivisionsを調整する機能はありません。
細かいマスクを必要とするモデルを扱うときには注意が必要です。

上の図はUnityで使用されるGloabalMaskTextureのRenderTextureをモデルと一緒に描画したものです。
右下の黒い部分がRenderTextureを描画したもので、左下から上へ下記の並びとなっています。

Mark1の目、Mark1の目、Mark1の口、名執の眼鏡、
名執の右目、名執の左目、Mark2の目、Mark2の目、
Mark2の口

同一のアートメッシュから生成されるマスクは統合されます。
これはマスクに使う番号を見ているわけではなく、インスタンス化したDrawableオブジェクトで比較しています。
そのため同一のモデルデータであっても複数インスタンスが存在した場合、インスタンスの数だけマスクを消費します。

マスクの上限に達した場合は実行時の登録順の遅いほうから、全面にマスクが掛かり表示が消えます。

また、マスクをかける側を内包する正方形で形状を取るため、大きなアートメッシュに小さなアートメッシュでマスクをかけても歪みにくい特性があります。

※AssetBundle化の際の注意

AssetBundle化した際にGloabalMaskTextureのRenderTextureが開放されない仕様があります。
メモリリークを起こさないためにチュートリアルの「AssetBundleからモデルを使用するとメモリリークする問題と対策」を確認してください。

Cubism SDK for Native、Cubism SDK for Web、Cubism SDK for Java

Cubism SDK for Native、Cubism SDK for Web, Cubism SDK for Javaでのマスクはモデル単位で冒頭で用意されます。
詳しくは「マスクの前処理方式」を確認してください。

Cubism SDK for Native、Cubism SDK for Web、およびCubism SDK for Javaではモデルごとにモデル内の描画順での描画機能しかないため、マスクの共有はモデル単位で行われます。
Unity同様同一マスクは統合されます。比較はDrawableの番号のみで行われます。
マスクの取り扱い枚数は最大36枚で、サイズは枚数によって自動的に調整されます。

上の図はCubism SDK for Nativeのクリッピングテクスチャを横に描画したものです。(Cubism SDK for Webでも同様の結果になります)
Cubism SDK for Native、Cubism SDK for Web、およびCubism SDK for JavaではCubism SDK for Unityと違って上下が逆転していることと、暗い方がマスクが描画されていることに注意してみてください。
描かれているのはMarkの右目、左目、口の3枚です。

Cubism SDK for Unityと違い、隣接するマスクバッファの影響を受けないためにマスクをかけられる側を内包する矩形で生成します。
このため、分割枚数が多い状態で大きなアートメッシュに小さなマスクが掛かるようなモデルでは、マスク領域がつぶれてしまい描画結果に影響が出る場合があります。
小さなマスクを離れた複数のアートメッシュに対してかける場合も同様です。
マスク領域がつぶれてしまう現象が発生した場合、マスクバッファのサイズを大きくすることで改善する場合があります。
(参考:マスクバッファの動的なサイズ変更)

また、Cubism SDK for Native、およびCubism SDK for Javaでは、パフォーマンスを引き換えにして高精細なマスクを使用する機能があります。
高精細マスクの有効化については『マスクの前処理方式(Native)#マスクの処理を高精細な方式に切り替える』、または『マスクの前処理方式(Java)#マスクの処理を高精細な方式に切り替える』をご覧ください。

描画順管理

Cubism SDK for Unity

Cubism SDK for Unityでは描画順の管理をUnity機能とスクリプトによって行っています。

方式は4つ。大分して2つの方法があります。

・Z調整(Back To Front Z、Front To Back Z)

モデル内のDrawableのZ位置をずらしてZソートによって描画順を修正する方法です。
カメラの設定がPerspectiveだったり、モデルのTramsformが回転していたりすると表示が乱れる可能性があります。
180度回転すると描画順は反転します。
描画順はすべてのDrawableに共通して同じ順序が振られます。

・Order調整(Back To Front Order、Front To Back Order)

モデル内のDrawableの描画順自体を一つづつずらして修正する方法です。
カメラの設定やモデルの回転で表示は乱れません。裏面であっても描画順はカメラに向かって同一です。
CubismRenderControllerのOrder In Layerを各モデルで十分に空けない場合、
描画順が混在し、細かく切り替わる状態になります。
DrawCallが増大したり、表示位置が被った状態だとDrawableが混じった表示になることがあります。

逆にUnityのオブジェクトなどをモデルの描画に挟み込むことにより、オブジェクトを持ったように見せかけたりすることもできます。

Cubism SDK for Native、Cubism SDK for Web、Cubism SDK for Java

Cubism SDK for Native、Cubism SDK for WebおよびCubism SDK for Javaではモデルに紐づけられたRendererの中身で描画順をソートします。

// Cubism SDK for Native
void CubismRenderer_OpenGLES2::DoDrawModel()
{
  ・
  ・
  ・
    const csmInt32 drawableCount = GetModel()->GetDrawableCount();
    const csmInt32* renderOrder = GetModel()->GetDrawableRenderOrders();
 
    // インデックスを描画順でソート
    for (csmInt32 i = 0; i < drawableCount; ++i)
    {
        const csmInt32 order = renderOrder[i];
        _sortedDrawableIndexList[order] = i;
    }
 
    // 描画
    for (csmInt32 i = 0; i < drawableCount; ++i)
    {
        const csmInt32 drawableIndex = _sortedDrawableIndexList[i];
 
		・
        ・(中略)
        ・
 
        DrawMesh(
            GetModel()->GetDrawableTextureIndices(drawableIndex),
            GetModel()->GetDrawableVertexIndexCount(drawableIndex),
            GetModel()->GetDrawableVertexCount(drawableIndex),
            const_cast<csmUint16*>(GetModel()->GetDrawableVertexIndices(drawableIndex)),
            const_cast<csmFloat32*>(GetModel()->GetDrawableVertices(drawableIndex)),
            reinterpret_cast<csmFloat32*>(const_cast<Core::csmVector2*>(GetModel()->GetDrawableVertexUvs(drawableIndex))),
            GetModel()->GetDrawableOpacity(drawableIndex),
            GetModel()->GetDrawableBlendMode(drawableIndex)
        );
    }
}
// Cubism SDK for Web
public doDrawModel(): void {
  ・
  ・
  ・
  const drawableCount: number = this.getModel().getDrawableCount();
  const renderOrder: Int32Array = this.getModel().getDrawableRenderOrders();
 
  // インデックスを描画順でソート
  for (let i = 0; i < drawableCount; ++i) {
    const order: number = renderOrder[i];
    this._sortedDrawableIndexList.set(order, i);
  }
 
  // 描画
  for (let i = 0; i < drawableCount; ++i) {
    const drawableIndex: number = this._sortedDrawableIndexList.at(i);
 
    ・
    ・(中略)
    ・
 
    this.drawMesh(
      this.getModel().getDrawableTextureIndices(drawableIndex),
      this.getModel().getDrawableVertexIndexCount(drawableIndex),
      this.getModel().getDrawableVertexCount(drawableIndex),
      this.getModel().getDrawableVertexIndices(drawableIndex),
      this.getModel().getDrawableVertices(drawableIndex),
      this.getModel().getDrawableVertexUvs(drawableIndex),
      this.getModel().getDrawableOpacity(drawableIndex),
      this.getModel().getDrawableBlendMode(drawableIndex),
      this.getModel().getDrawableInvertedMaskBit(drawableIndex)
    );
  }
}
// SDK for Java
@Override
protected void doDrawModel() {
    ...
 
    final int drawableCount = model.getDrawableCount();
    final int[] renderOrder = model.getDrawableRenderOrders();
 
    // Sort the index by drawing order
    for (int i = 0; i < drawableCount; i++) {
        final int order = renderOrder[i];
        sortedDrawableIndexList[order] = i;
    }

    ...
 
    // Draw process
    for (int i = 0; i < drawableCount; i++) {
        final int drawableIndex = sortedDrawableIndexList[i];
        ...
 
        drawMeshAndroid(
            model.getDrawableTextureIndex(drawableIndex),
            model.getDrawableVertexIndexCount(drawableIndex),
            model.getDrawableVertexCount(drawableIndex),
            indexArrayBuffer,
            vertexArrayBuffer,
            uvArrayBuffer,
            model.getMultiplyColor(drawableIndex),
            model.getScreenColor(drawableIndex),
            model.getDrawableOpacity(drawableIndex),
            model.getDrawableBlendMode(drawableIndex),
            model.getDrawableInvertedMask(drawableIndex) // Whether the mask is used inverted
        );
    }
    postDraw();
}

モデル間で表示が混じることはありません。
モデル間では先に描画したほうが後ろに表示されます。

モーションの管理

Cubism SDK for Unityではモーションの管理をUnity機能であるMecanimと、UnityのPlayable APIを利用したSDK付属のコンポーネント「CubismMotionController」の2種類を使用して行います。
Mecanimではグラフィカルな環境で視覚的にモーションの組み合わせを設計できます。
CubismMotionControllerでは状態を気にせずすべてスクリプトからモーションを再生することが出来ます。

Cubism SDK for Native、Cubism SDK for WebおよびCubism SDK for JavaではLive2D側のSDKでモーション管理を行います。
直接コードで操作する形になりますが、ポーズ機能などCubism 2.1に近い形での運用ができます。

詳しいSDKによるモーション関連の違いについては「SDKによるモーション作成の違いについて」を参照してください。

この記事はお役に立ちましたか?
はいいいえ
この記事に関するご意見・
ご要望をお聞かせください。