FBXなどからインポートしたアニメーションのサイズを小さくする。

前置き

2017年になってもスマートフォンの搭載メモリはたいして増えてなくて、結局アプリで使うメモリを300MB~400MBくらいに押さえないといけない。なので少しでもファイルサイズやメモリを削るようにしないとアプリが落ちてしまって困ったことになる。(古い端末を対象外にすればいいけどいろんなしがらみがあって大体サポートしないといけない)

3Dゲームの場合、テクスチャサイズはそこまで大きくしなくても見た目は許容できるので、相対的にアニメーションのサイズが問題になることが多い。(解像度が高いけどGPU性能がそうでもない端末が多いのからあまり複雑なシェーダも使えないのでテクスチャの枚数も少なくてすんでいる)

Unityでアニメーションのインポート時の設定によってアニメーションサイズがどのくらい変わるか調べてみた。

インポート設定によるアニメーションサイズの比較

SDユニティちゃん 3Dモデルデータをアセットバンドル化したときのログからアニメーションのサイズを比べてみた。(Unity 5.5.3p4)

デフォルトの状態(圧縮なし)

Compressed Size:4.0 mb
Uncompressed usage by category:
Textures       2.7 mb    30.3% 
Meshes         872.9 kb  9.5% 
Animations     5.1 mb    57.1% 
Sounds         0.0 kb    0.0% 
Shaders        105.1 kb  1.1% 
Other Assets   77.2 kb   0.8% 
Levels         0.0 kb    0.0% 
Scripts        0.7 kb    0.0% 
Included DLLs  0.0 kb    0.0% 
File headers   90.7 kb   1.0% 
Complete size  8.9 mb    100.0%

Keyframe Reduction

Compressed Size:2.4 mb
Uncompressed usage by category:
Textures       2.7 mb     51.7% 
Meshes         872.9 kb   16.3% 
Animations     1.4 mb     26.9% 
Sounds         0.0 kb     0.0% 
Shaders        105.1 kb   2.0% 
Other Assets   77.2 kb    1.4% 
Levels         0.0 kb     0.0% 
Scripts        0.7 kb     0.0% 
Included DLLs  0.0 kb     0.0% 
File headers   90.7 kb    1.7% 
Complete size  5.2 mb     100.0%

圧縮設定をOptimal

Compressed Size:2.0 mb
Uncompressed usage by category:
Textures       2.7 mb    56.7% 
Meshes         872.9 kb  17.8% 
Animations     969.3 kb  19.8% 
Sounds         0.0 kb    0.0% 
Shaders        105.1 kb  2.1% 
Other Assets   77.2 kb   1.6% 
Levels         0.0 kb    0.0% 
Scripts        0.7 kb    0.0% 
Included DLLs  0.0 kb    0.0% 
File headers   90.7 kb   1.9% 
Complete size  4.8 mb    100.0%

圧縮設定をOptimal、Resample Curvesのチェックを外す

Compressed Size:1.9 mb
Uncompressed usage by category:
Textures        2.7 mb     58.1% 
Meshes          872.9 kb   18.3% 
Animations      859.1 kb   18.0% 
Sounds          0.0 kb     0.0% 
Shaders         105.1 kb   2.2% 
Other Assets    77.2 kb    1.6% 
Levels          0.0 kb     0.0% 
Scripts         0.7 kb     0.0% 
Included DLLs   0.0 kb     0.0% 
File headers    90.7 kb    1.9% 
Complete size   4.7 mb     100.0%

まとめ

  • 圧縮なし 5.1MB
  • 圧縮あり(Keyframe Reduction) 1.4MB
  • 圧縮あり(Optimal) 969.3KB
  • 圧縮あり(Optimal)+Resample Curvesのチェックなし 859.1KB

圧縮しないと大きすぎるので基本的にはOptimalにしておく。Resample Curvesのチェックをなしにすると小さくなるがイマイチどんな設定かよく分かってないので元のモーションから大きくずれてないか確認する必要がありそう。

UnityのWWWクラスでダウンロードした後にtextやbytesにアクセスするとそのたびにメモリが確保されているみたい。

以下のようなテストコードを用意する。

WWW www = new WWW(url);

while (!www.isDone)
{
    yield return null;
}

Profiler.BeginSample("///// www.bytes");

// 適当な回数だけbytesにアクセスする
int size = 0;
for (int i = 0; i < n; i++)
{
    size = www.bytes.Length;
}

Profiler.EndSample();

1回だけアクセスのときGC Allocは68.5KB

100回アクセスしたときGC Allocは6.7MB

まとめ

WWWクラスのbytesやtextにアクセスするときは1度だけにすること。

PictBearでアルファチャンネルを表示するプラグインを作った。

メニューのフィルタ/カラー/アルファチャンネルから実行する

https://github.com/sapphire-al2o3/ColorChannel/releases

ループしないアニメーションの遷移でハマったのでメモ。

上昇したら止まって、適当なパラメータが有効になったら下降するアニメーションを作成する。

上記のようなステートをもつAnimatorControllerを用意する。up(3秒かけてy:0からy:5に上昇する)からdown(3秒かけてy:5からy:0へ下降する)への遷移はboolのパラメータがtrueの場合に遷移する。

このときupがループアニメーション出ない場合、up最後のフレームでアニメーションは止まっている。Has Exit Timeにチェックが入っているとパラメータがtrueになったときにすぐにdownに遷移せずに一定時間待つとdownのアニメーションが始まる。

どうやら表示的にはアニメーションのタイミングは最後までいっているが、内部的にはループしているため3秒ごとに遷移タイミングがきている。上昇アニメショーンが終わっていて、パラメータがtrueになったらすぐに下降アニメーションをさせたい。

解決方法

上記のようにステートを1つ追加する。ここで追加したloopのステートはアニメーションをつけないでWrite Defaultsのチェックもオフにする。

そしてupからloopへの遷移はHas Exit Timeを有効にして、loopからdownの遷移はHas Exit Timeを無効にしてパラメータがtrueのときに遷移するようにする。

こうすることでupのアニメーションが終わるとloopステートに遷移して、loopステートからdownステートへはHas Exit Timeが無効なのでパラメータがtrueになったら即座に遷移するようになる。

サブウェポンとかも描き出した。(2015/10)

2015_october_dot

なんで載せるのが遅かったかというとTwitterの仕様変更でPNGがJPEGにされるようになって透過色使ってなかった画像がサルベージできなくなったから。

スプラトゥーンの武器だらけ。

september2015_dot

これ描いたの一昨年だ…

投稿者 tel | 2017年1月6日

2017年

2017

あけましておめでとうございます。
今年はたくさんアウトプットしたいです。

何らかの理由でRendererについているマテリアルがmissingになってしまったときを検出する場合はrenderer.sharedMaterialがnullかどうかでチェックする。
https://docs.unity3d.com/jp/current/ScriptReference/Renderer-sharedMaterial.html

missing_ss

マテリアルがmissingだとピンク色になる。(エラーのシェーダでレンダリングされている)

missing_ss2

Debug.Assert(renderer.sharedMaterial != null);

sharedMaterialを参照するとAssertに引っかかる。

Debug.Assert(renderer.material != null);

materialを参照するとgetした瞬間に新たなマテリアルが生成されてしまうのでAssertが通ってしまう。

ちなみにmissingになっているときにmaterialをgetして生成されるマテリアルは実行環境によって異なる。(おそらくシェーダの有無で違う)

投稿者 tel | 2016年11月23日

UnityでMenuItemが動かない

MenuItemで追加したメニューから関数が呼ばれなかった場合があったのでメモ。(Unity 5.4.2)

以下のようにMenuItemの関数と同じ名前のオーバーロードされた関数を用意するとメニューは項目が追加されるが選択しても関数が実行されなかった。

public class MenuItemTest : Editor
{
    static void Test(int i)
    {
    }

    [MenuItem("Editor/Test")]
    static void Test()
    {
        Debug.Log("test");
    }
}

ちゃんとメニューには出てくる。
menu_item_ss

ただし以下のようにオーバーロードされた関数をあとに書いておくと実行される。

public class MenuItemTest : Editor
{
    [MenuItem("Editor/Test")]
    static void Test()
    {
        Debug.Log("test");
    }
    static void Test(int i)
    {
    }
}

Unity 5.5では直っていた。
https://issuetracker.unity3d.com/issues/override-existing-menu-items-does-not-work-until-reimporting-scripts

ParticleSystem.Pause を呼び出してパーティクルをポーズして、再度Playして一時停止を解除するとStart Delayの経過時間がリセットされている挙動をする。つまりPauseとPlayを交互に繰り返すと、いつまでたってもパーティクルが放出されない。

エフェクトの一時停止をしようとした場合、Start Delayが設定されているパーティクルは再生時間がずれてしまい困ったことになる。

https://docs.unity3d.com/ja/current/ScriptReference/ParticleSystem-startDelay.html

どうやらバグのようだが、Issue Trackerでは直ったことになっている。

https://issuetracker.unity3d.com/issues/shuriken-particlesystem-dot-pause-resets-start-delay
https://forum.unity3d.com/threads/5-3-5p5-754270-particles-start-delay-still-have-problem.413072/?_ga=1.122247371.1793905693.1359169028

続きを読む…

Older Posts »

カテゴリー