読者です 読者をやめる 読者になる 読者になる

テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

【Unity】ノベルゲームの立ち絵表現で、キャラクターの表情だけ切り替えて、メモリとロード時間を節約する

f:id:tsubaki_t1:20160401224745j:plain

ついにユニティちゃんの立ち絵素材が公開されましたよ。超可愛いユニティちゃんとユーコちゃん*1、あとミサキちゃんの立ち絵が使えるようになった!ヤッタネ

 

さらに嬉しい事に解像度は1620×2048と非常に高解像度で、キャラクター全体像をのイメージが使用されているよ!
なんと1キャラに表情を5つ用意するとメモリを85MB、それを3体表示するとメモリを255MBも消費出来るよ!ブイブイ

 

さらにこんな大きなテクスチャであればロード時間も追加出来るよ!
5.3から非同期なテクスチャロードも出来るようになったけど完璧なシームレスでは無いから、ゲームをガっと止めるカクカクに出来るよ!イエイ☆

f:id:tsubaki_t1:20160401230843j:plain

まあ、最近のモバイルだと実はLZMA圧縮したAssetBundleとかandroidのresourcesから持ってこない限り)結構高速で読めるし、メモリも(コンソールと違って)潤沢にあるので最悪コレでも良いのですが、もう少し何とかしたい気持ちもあるので、何とかしてみます。

表情だけを切り替えるアプローチ

今回のユニティちゃんの立ち絵は、基本的に表情しか変化していない立ち絵です。つまり、表情の部分「だけ」を保持しておいてベースとなる顔に上書き…とすることで、容量を大幅に節約出来そうです。

f:id:tsubaki_t1:20160401230808j:plain

こんな感じで、立ち絵の体のような重複部分をまとめていくと、キャラクターの5表情を表示するためのメモリ消費量とファイルサイズが85MBから16MBくらいにまで落ち着きました
キャラ5体換算だと255MBから48MBです。

さらにPOTを意識してまとめればテクスチャ圧縮も出来るので、1キャラ表情5種の3体で合計12MBくらいまで落とせますが、圧縮によっては透明との境目が結構汚くなるので、まぁ(顔だけTrueColorでも良いけど)。

表情をくり抜く

ここで問題となるのが、くり抜く表情の座標です。くり抜く表情の座標は常に固定ではないので、各立ち絵事に座標を保持・運用する必要が出てきます。もしくは、スプライトのオフセットを透明部分を元に設定しておく必要があります。

 

それを手抜きするため、SpritePackerの機能を活用します。SpritePackerは透明な部分を抜き座標を保持したままパッキングしてくれる機能です。つまり、表情以外を透明にすれば、顔の位置を保持したままパッキングしてくれます。

f:id:tsubaki_t1:20160401231622j:plain

f:id:tsubaki_t1:20160401231705j:plain

PNGの方の立ち絵の、顔以外を透明で塗りつぶせばこんな感じに出来ます。顔の位置変更とかはしなくてもOKです。というか、したら駄目です。
抜き方?GIMPPINGの画像に対して、消しゴムで不要な部分を全部くり抜いただけです。

 

なお、画像は「加算合成」なので、輪郭線のようにアルファ(半透明)を使用している部分があると、そこだけ強く見えてしまう事があるみたいです。
なので、手前に表示する顔には「アルファが含まれないようにする」のが良さそうです。もしくは合成しても良いように「基本のボディから表情を抜く」か。首の上と下で分けちゃうのも簡単かもしれません。

顔の部分だけ差し替える

次はゲームで、顔の部分だけを差し替える方法について考えます。といってもやる事は一つ「体より前面に顔を表示する」だけです。Imageならば体の子として表情を持っておけばOKです。

また、座標やスケールは「体と顔で一致」させます。そうすれば、SpritePackerが残してくれたサイズから位置が一致します。

f:id:tsubaki_t1:20160401233846g:plain

なお、この方法だとキャラクター全体を2回描画するような事になりそうですが、実際に塗りつぶす範囲は、キャラクターの表情部分だけです。

f:id:tsubaki_t1:20160401234839j:plain

この表現にSpriteRendererを使用する場合は、描画順の設定にOrderInLayerを使用します。ただ描画順によっては他キャラクターの体の前に顔が表示される事があるので注意が必要です。例えば、下の絵ではミサキちゃんの手前にユニティちゃんの表情が表示されています。コワイ!
キャラの描画順事にOrderInLayerを大げさに調整するのが良さそうです。

f:id:tsubaki_t1:20160401234433j:plain

解像度を下げて更に負荷ダウン

もっとメモリ消費量を減らそうと思ったら、解像度を下げるのが手っ取り早いです。例えば下の画像は、顔と体合わせて512kbくらいになります。

f:id:tsubaki_t1:20160402000302j:plain

じつは上の画像、顔と体で解像度が異なります。具体的には顔は1024クラス解像度で(範囲が小さいので、実際は300くらい)、体は512の解像度でテクスチャを保持しています。

f:id:tsubaki_t1:20160402001036j:plain

f:id:tsubaki_t1:20160402001052j:plain

これは自論ですが、キャラクターの立ち絵を見る時に一番見るのが「顔」だと自分は考えています(次点でユーザーのフェチなパーツ)。なので、最も注視する顔だけでもクッキリ表示されていれば、解像度を少し下げても解像度が低い印象を受けないのではないか…という事です。(流石に差がありすぎると境目がハッキリ見えてボケたイメージになります。また、一発で低解像度だと分かる解像度では使えません)

これはUIとかも同じで、ボタンや文字の境目等の注視するパーツがボケていると解像度が低い印象を受けますが、逆に見る部分だけでもクッキリしていると、案外綺麗に見えたりします。なお、このアプローチはデザイナーの方と喧嘩になるので、用法容量は正しくお使いください。
(似たようなアプローチに、Normalだけ高解像度でDiffuseはそこまで高解像度にしなくても、結構綺麗に見れるってのがあるみたい)

感想

何はともあれ、(やったねたえちゃんかぞくがふえるよ)
これでユニティちゃんのゲームの会話パートとか簡単に作れるようになりそうです。

そして今回の内容を元に会話パートの記事を作り直したい欲が…
(以前と違ってAssetBundleをPersonalでも使えるので、リソースをAssetBundleから取得する前提で、実行時テキスト読込みたいな無駄な事を省いたやつ)

 

(本当はのっぺらぼう+表情以外は透明…みたいな事をやらないといけないと思うんだけど、GIMP非対応だから無理だったよ)

関連

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp

unity-chan.com

http://unity-chan.com/images/imageLicenseLogo.png

 
 

*1:個人的に一番お気に入り