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

#6 「今年UnityのAssetBundle周りで頑張った事」 tech.kayac.com Advent Calendar 2013

unity AdventCalendar2013

こんばんはo(^▽^)o

Unityエンジニアとして今年4月に入社したけど7月まで@songmu先生の元でPerlを教わりながら書いてたけど、夏休みから戻ったら再びUnityエンジニアとして働く事になってた@p_chin です!

早く忘年して今年の苦悩を昇華できたらいいなーって思ってます!(フラグ

このエントリーはtech.kayac.com Advent Calendar 2013の6日目のエントリーだよヾ(@⌒ー⌒@)ノ

実はPerl書いてた頃の方が既存のイノベーションに触れる事が多かったのだけど、

今年、UnityのAssetBundleに関する自動化周りのイノベーションを起こすべく、先輩方に助けられながら頑張ってる(今もまだ頑張ってる…)ので、その事について書いて行きまーす(^ー^)ノ

もくじ

前置き

  • UnityのProjectはgitで管理しております
  • AssetBundleをビルドするUnityProjectは、ゲーム制作のProjectとは分けて別管理してます
  • AssetBundleやAtlasのビルドは基本的にjenkinsに任せてます

Textureの設定をAssetPostprocessorで自動化

2Dゲームを作成していると、設計にもよりますが大量のTextureのAssetBundleの配信する事になると思います。

その為、開発中におけるAssetBundleの更新頻度が高くなると、画像をUnityProjectに配置すると,TextureのImportSettingsを都度設定しなければいけないので、AssetPostprocessorのサブクラスが使えるOnPreprocessTextureメソッドの中に配置された画像のpathをRegexでチェックして、適切なTextureImportSettingを自動で設定する仕組みをまず書きました。

using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Text.RegularExpressions;

class TextureModifier : AssetPostprocessor
{
    void OnPreprocessTexture ()
    {
        if (Regex.IsMatch(assetPath, @"Assets/AssetBundleResources/Fugu/fugu_icon_s/.*\.png$")) {
            var importer = (assetImporter as TextureImporter);

            importer.textureType = TextureImporterType.Advanced;
            importer.compressionQuality = (int)TextureCompressionQuality.Best;
            importer.npotScale = TextureImporterNPOTScale.None;

            importer.isReadable = true;
            importer.generateCubemap = TextureImporterGenerateCubemap.None;
            importer.filterMode = FilterMode.Bilinear;
            importer.mipmapEnabled = false;
            importer.anisoLevel = 0;
            importer.wrapMode = TextureWrapMode.Clamp;
            importer.alphaIsTransparency = true;
            // device setting
            importer.SetPlatformTextureSettings ("Android", importer.maxTextureSize, TextureImporterFormat.ATC_RGBA8);
            importer.SetPlatformTextureSettings("iPhone", importer.maxTextureSize, TextureImporterFormat.RGBA16);
        }
    }
}

OnPreprocessTexture()に設定を書いておくと、TextureのImportSettingsが変更された時もこのメソッドが働いてくれるので、UnityEditor内のInspectorからはカジュアルに設定を変えられないので、設定の人的ミスは避けられますね!

AtlasとAssetBundleの自動ビルド

Unityのコマンドライン起動について

現在AtlasとAssetBundleの生成はjenkinsのjobからUnityをコマンドラインから起動してEditorScriptのメソッド実行してます。

基本的にはUnityEditorを立ち上げない-batchmodeオプションで起動させますが、その場合だとScene内でアレコレする事が出来ないので、そんな時は-batchmodeオプションを外して-executeMethod <ClassName.MethodName>オプションを付けて実行すると、UnityEditorが表示されてScene内でアレコレやれたりします。

というのを、最近私の隣で仕事をしている@onevcatから教えてもらいましたので、おススメです。

Atlas自動ビルドにおける苦悩

Atlasの生成はNGUI2.6.3のUIAtlasMaker.AddOrUpdateを使ってるのですが、Atlasにまとめる画像の数が多いと、たまにUIAtlasのSpriteがずれたりするのでまだ課題があります。

ちなみにAssetBundleの生成は、特に失敗とかは無くて安定してます。

自動ビルドのScriptは秘伝のタレ化が進み、汎用化出来てないの為ここでは見せられなかったです。。。

jenkinsにビルドさせてリポジトリにcommitさせちゃってます

余りお行儀が良くないのですが、AssetBundleのProjectはリソースを淡々と追加していくだけなので、master branchにgit push -fさせてます。

人間でcommitするのが、私か素材を置いてくれるデザイナーだけだし、jenkinsは生成したAtlasとAssetBundleしかcommitしないので、コンフリクトは今の所は起きて無いです。

画像の圧縮についての小ネタ

  • PVRTC4bit

これが皆さんご存知の通り、グラデーションや透過部分の多い画像にかけてしまうと劣化が顕著に現れてしまいますので、背景とかならまだしも、何の対処も無しに厚塗りのキャラクター画像などに圧縮をかけてしまうと、デザイナーからブーイングが来ます。

これに関しては画像によって最適な圧縮が異なるので、常にUnityエンジニアとデザイナーが納得いくまで時間をかけてチューニングして行くしか無いのかな…とは思ってます。

今が、PVRTCにするものの、画像の解像度をあげてゲーム内での表示の品質をあげようとしてますが、これも今度はアプリケーションが実行されるメモリが増えて辛いので、下手に解像度が挙げられないのでギリギリまでチューニングしてます。

  • RGBA16bit

PVRTC4bit圧縮がダメなら16bitに落ち着く..くらいだと思います。

ですが、16bitRGBAをNGUIのAtlasに適用したままでNGUI2.6.3のUIAtlasMaker.AddOrUpdateを実行してAtlasの中身を更新すると、エラーが出ます。

原因は、Atlasを作詞絵する時に、画像のpixelを操作するからです。

Texture2Dのpixel操作は、RGBA32bitなどのトゥルーカラーの画像しか出来ないのが理由です

Unityのリファレンスにも書いてありますので、こちらもよろしければご覧下さい。

まとめ

AssetBundleサイコーだから、もっと色々な現場の頑張りを公開してこ!

という適当な締めをさせて頂きます!

以上となりますが、少しでも為になって頂ければ嬉しいです。

乱文失礼致しました。


さて明日の記事を書くのが、面倒見の良いiOSに詳しいイケメンおじさんかと思いきや、エロコンテンツの作成にも腕を鳴らしていらっしゃる@SOMTDさんです!

お楽しみに!