投稿者 tel | 2016年10月17日

すみだ水族館

9月の23日にすみだ水族館に行ってきた。2050円。

img_20160923_144540

img_20160923_123911

img_20160923_124213

img_20160923_125048

テヅルモヅルかなにか。

img_20160923_132147

チンアナゴ

img_20160923_140248

img_20160923_135931

img_20160923_135848

img_20160923_140026

ちょうど金魚展をやっていた。

新しいので内装がきれいでおしゃれだった。料金高めの割には魚の種類は他の水族館に比べると少ない。

img_20160923_150111

曇っていたのでスカイツリーの上の方は見えなかった。

投稿者 tel | 2016年10月12日

UnityのSphereのポリゴン

デフォルトのSphereのポリゴンがUnity4とUnity5で違っていることに最近気づいた。

sphere2 sphere

Unity 4.6.9とUnity 5.4.1のSphereのメッシュ。

Unity5のほうが頂点数が減って、ポリゴン数が増えている。また見た感じ三角形の面積が均一になっている。
UVも変わっているようで、テクスチャを貼り付けた結果が変わっていた。

tile2

上記のテクスチャを貼り付けてみる。

tex_4_ss tex_5_ss

Unity5のほうが極付近UVがきれいになっている。

投稿者 tel | 2016年10月11日

CEDEC2016

今年もCEDECに行ってきました。いろいろあって2日目の8/25、1日だけ。

とくに面白かったのは「ラピッドイテレーションを実現するゲームエンジンの設計」。カプコンのREエンジン開発でのセッション。REエンジンはバイオハザード7で使用しているエンジンらしい。

  • プログラミング言語としてC#を採用している。
  • C#のVMも自作している。
  • またリリース時にはIL2CPPでC++に変換している。(Unityの使ってるIL2CPPとは別物)
  • C#を使用するときに問題になるGCによるフリーズを解消するために専用のGCを作成している。

レッドブルは1年でCEDECで配っているのくらいしか飲まないが今年は飲み忘れた。

img_20160825_175440

CEDEC AWARDはスプラトゥーンが3冠とってた。スプラトゥーンは技術的な話も聞いてみたいのでなにかセッションがあればよかったのに。

テクスチャのインポート設定からMax Sizeで縮小した場合の表示がUnity4とUnity5で違っているみたいなので調べてみた。

元画像(256×256)

tile

インポートの設定でMax Sizeを128、FormatをTrue Colorにする。

import_ss

Unity5(5.4.0)での結果

tile_unity5_ss

Unity4(4.6.9p4)での結果

tile_unity4_ss

Unity4は白と黒の色しか出ていないが、Unity5の方は灰色になってしまっている。

元画像の線やタイルのパターンは2ドットのサイズで描いているので単純に半分に縮小したらUnity4の結果のように周囲の色が混ざらない方が自然だと思う。

ピクセルの配置によっては意図しないアーティファクトが出てしまう場合があるので、Max Sizeよりも大きいテクスチャはあらかじめ縮小しておいたほうがよさそう。

投稿者 tel | 2016年9月10日

一定周期の三角波

前にノコギリ波を作ったので今度は三角波を作る。

一定の周期のノコギリ波

まず高さが1のノコギリ波を作る。

float x = fract(t)

tr4

0.5引く。

tr3

絶対値を取る。

tr2

2倍すると高さが1の三角波になる。

tr
float tt = abs(fract(t) – 0.5) * 2.0

WWWに代わるAPIとしてUnityWebRequestがUnity5.4から正式に使えるようになったのでファイルをダウンロードして保存する処理を作ってみる。

従来の問題点

WWWを使ってファイルをダウンロードして保存しようとした場合、ダウンロードが完了してからWWW.bytesのデータをファイルとして保存する。WWW.bytesにアクセスするとMonoメモリ上にダウンロードしたデータがまるごと確保されてしまい、大きなファイルをダウンロードしようとしたときに一気にMonoのピークが上がってしまう。

特にモバイル系だとメモリが厳しいのでファイルのダウンロード後にゲームを続けるとすぐに落ちてしまう事態に陥る。

DownloadHandlerScript

UnityWebRequestではダウンロードの挙動をdownloadHandlerで変えることができる。

DownloadHandlerScriptを継承したクラスを用意することで、ダウンロードデータの受信時に直接ファイルに書き込むことができる。つまり今までの全部ダウンロードしてからファイル保存から、少しずつダウロードして都度ファイルに書き込むようにできるためメモリの消費が減らせる。
またコンストラクタにあらかじめ確保したバッファを渡すことで、受信時にそのバッファが使われるようになる。毎回バッファが生成されなくなるため断片化しづらくなる。

class FileDownloadHandler : DownloadHandlerScript
{
    FileStream fs;
    int offset = 0;
    int length = 0;

    public FileDownloadHandler(string path, byte[] buffer)
        : base(buffer)
    {
        fs = new FileStream(path, FileMode.Create, FileAccess.Write);
    }
    // データを受信すると呼び出される
    protected override bool ReceiveData(byte[] data, int dataLength)
    {
        fs.Write(data, 0, dataLength);
        offset += dataLength;
        return true;
    }
    // ダウンロードが終わった時に呼び出される
    protected override void CompleteContent()
    {
        fs.Flush();
        fs.Close();
    }
    // ダウンロードするサイズ
    protected override void ReceiveContentLength(int contentLength)
    {
        length = contentLength;
    }
    // downloadProgressの値
    protected override float GetProgress()
    {
        if (length == 0)
            return 0.0f;

        return (float)offset / length;
    }
}

上記のようなファイル保存用のクラスを用意して、インスタンスをUnityWebRequest.downloadHandlerに設定する。Sendを呼び出すとダウンロードが開始される。

実験

それぞれの場合でダウンロードしてファイル保存するのにMonoのメモリ(Profiler.GetMonoHeapSize)がどれだけ増えるか調べた。WWWとUnityWebRequest.Getはダウンロードした後でFile.WriteAllBytesでファイルに保存している。DownloadHandlerScriptには256KBのバッファを渡している。

  • WWW
  • UnityWebRequest.Get
  • DownloadHandlerScript

計測環境

  • Nexus7 2012
  • 13,981,285MBのファイル

結果

  • ダウンロード前: 684,032 (byte)
  • WWW: 14,798,848 (byte)
  • UnityWebRequest.Get: 14,798,848 (byte)
  • DownloadHandlerScript: 1,175,552 (byte)

まとめ

  • メモリのピークが1桁くらい違っているのでUnityWebRequestを使うのは非常に有効
  • 途中で通信が切れた場合とかのエラー処理をちゃんと書かないといけない

参考

投稿者 tel | 2016年8月3日

MonoDevelopのコード整形を無効にする

MonoDevelopで勝手にコード整形されないようにする方法。

mono_ss

OptionからBehaviorのEnable on the fly code formattingのチェックを外す。

投稿者 tel | 2016年7月19日

AnimatorOverrideControllerのメモ

UnityのAnimatorOverrideControllerを使うと既存のAnimatorControllerのAnimationClipを置き換えることができる。
http://docs.unity3d.com/ja/current/Manual/AnimatorOverrideController.html
例えばゲームのモンスターのアニメーションでステートとトランジションは共通でバリエーションを作るときなど便利に使える。

ただアセットバンドル化した時に置き換えた元のアニメーションも含まれているようで、ファイルサイズが大きくなってしまった。

実験

  • アニメーションクリップClipAとClipBを割り当てたAnimatorCntrolerを作成する。(controller0、controller1)
  • AnimatorOverrideControllerを作ってClipAを割り当てたAnimatorControllerを参照し、ClipAをClipBで置き換える。
  • それぞれをアセットバンドル化する。

overridecontroller_ss

それぞれのファイルサイズは以下のようになった。

  • controller0:101KB
  • controller1:139KB
  • overridecontroller:226KB

まとめ

ステートを使い回す目的でOverrideAnimatorControllerを使うとアセットバンドルのサイズが大きくなってしまう。
そのためダミーのサイズが小さいアニメーションを付けておくか、AnimatorControllerを複製して使うような運用が必要になりそう。

投稿者 tel | 2016年7月15日

1ドットのアウトラインを描く

1ドットのアウトラインを描画する方法を考えてみた。

outline_ss outline_ss02

図のように緑の部分と青の境界部分に1ドットの赤い線を描く。

  • 緑の部分を塗りつぶし処理で領域を取得。
  • 塗りつぶした領域を収縮させる。
  • 収縮した部分を任意の色で描画する。

塗りつぶし

同じ色の範囲を領域として取得する。
領域取得用に2値の画像と同じサイズのバッファを用意する。効率は良くないが今回は再帰的に塗りつぶす手法を使った。

// c: 塗りつぶす範囲の色
// data: 元の画像
// tmp: 塗りつぶし範囲のバッファ
// x, y: 開始座標
(function f(x, y) {
    if(x >= w || x < 0) return;
    if(y >= h || y < 0) return;
    if(data[y * w + x] === c && tmp[y * w + x] === 0) {
        tmp[y * w + x] = 1;
        f(x - 1, y);
        f(x + 1, y);
        f(x, y - 1);
        f(x, y + 1);
    }
})(x, y);

領域収縮(erosion)

収縮は対象の領域を1画素分小さくする処理。注目した画素の周りに違う色の画素があった場合にその画素をけずる。
4近傍で見るので上下左右の画素をチェックしている。

for(var i = 0; i &lt; h; i++) {
    for(var j = 0; j &lt; w; j++) {
        var k = i * w + j,
            p = tmp[k] === 1,
            b = false;
        if(i &gt; 0) b |= tmp[k - w] === 0;
        if(i &lt; h - 1) b |= tmp[k + w] === 0;
        if(j &gt; 0) b |= tmp[k - 1] === 0;
        if(j &lt; w - 1) b |= tmp[k + 1] === 0;
        if(p &amp;&amp; b) {
            data[i * w + j] = newColor;
        }
    }
}

削った部分がアウトラインになるので指定の色で塗っている。

結果

outline_ss

紫色の部分を指定して中央の領域のアウトラインを白で描く。

outline_ss2

 

通常は適切なシェーダを使っていれば描画順番を気にする必要はない。どうしても半透明のものの重なりがうまくいかないときにMaterial.renderQueueを設定する。

http://docs.unity3d.com/jp/current/ScriptReference/Material-renderQueue.html

インスペクタをデバッグ表示にすれば設定できるが、それだと分かりづらいのでエディタ拡張でマテリアルのRenderQueueを設定できるようにする。

renderqueue_ss

RenderQueueでやるよりもRenderer.sortingOrderとかで設定したほうがいいかもしれない。

« Newer Posts - Older Posts »

カテゴリー