テラシュールブログ

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

アプリサイズを減らす その3

アプリサイズを減らす その2で紹介した方法(StreamingAssetsに配置する)だが、どうやらAndroidでは若干安定度に難がある。

で、もう少し良い方法を思いついた。

[Unity3D]iosアプリサイズを節約する
http://tsubakit1.hateblo.jp/entry/20120512/1336773155
[Unity]アプリサイズを減らす 2
http://tsubakit1.hateblo.jp/entry/20130121/1358778267

要はTexture2D.LoadImageでbytes配列を取得出来れば良いので、画像ファイルをbytesとしUnityのResourcesもしくはUnityプロジェクトに組み込んでしまう方法だ。

スクリーンショット 2013-08-05 23.55.19

Unityは拡張子がbytesとなるファイルは変換せずそのまま保持する仕様だ。なので、画像ファイルも拡張子をbytesとすれば内部的にはpngないしjpegで保持することが出来る。

この方法がStreamingAssetsより優れている点は4点。

・非同期ではなく同期的に読むことが出来る。
 同期的に読めるので、管理が簡単。

・日本語フォルダによる問題を回避出来る。
 Unityは日本語パスがあると読めない事があるので。

ビルド時・プラットフォーム切替時にインポーターが走らない

・ファイルが外部から簡単にアクセスされない


bytesではエディタ上で確認出来ないので、下のような形でエディタ上でも即確認出来るようにすると良さそうに感じる。NGUIとの連携は、多分UIAtlasに何か仕込むと良さげだと思う。

使い方は、適当なQuadにコレをアタッチし、*.png.bytesとリネームしたテクスチャをアタッチするだけ。その際、マテリアルは画像毎に用意しておくことをお勧め。
(バッチを効かせる為、shardMaterialを使用中)

スクリーンショット 2013-08-06 0.22.49

一応エディタ上では別のファイルをアタッチする度に更新するようになる。

当然、Resourcesに配置すればランタイムに読める。その場合も同様にTextAssetsとして取得しTexture2D.LoadImageでテクスチャ化する感じ。


一見便利な方法だが、相変わらずメモリ難になる問題は継承している(RGBA32で読込を行うため)。また、ローディングに必要な時間がAssetBundleと比較して約3倍かかるため、AssetBundleが使えるならAssetBundleを使ったほうが幸せになれる…場合もある。

(テクスチャのローディング高速化はまた今度)

Excelでデータを管理してUnity iOS/Androidで使うワークフロー

前回の応用で、Excelの中身をScriptableObjectとして保持するようにした。

tsubakit1.hateblo.jp

より良い方法があったので、そちらをどうぞ。
tsubakit1.hateblo.jp

Excelみたいなデータとして大きく効率が悪いフォーマットからランタイムで引っ張ってこようとすると、馬鹿みたいに時間がかかってしまうし、メモリも食い散らかしてしまう。

ScriptableObjectにすれば効率的にResourcesから動的に読み込んだり、シーン内に組み込んだりできる。それにJSONより小さい(バイナリベースなので)

そして何よりAndroid/IOSで使用できる。ScriptableObjectはUnityの基本機能なので、AOTだろうがJITだろうがiOSだろうがAndroidだろうがBasicだろうが関係なく使用出来る。
(この手の物はAOT≒iOSで動かない事がけっこう多い)

なので、Excel更新時にScriptableObjectに流しこむ部分を自動化した。

参考はコレ

unity3d-jp/XmlToCustomAsset
https://github.com/unity3d-jp/XmlToCustomAsset


作成したパッケージはコレ。

一連のパッケージ
https://dl.dropboxusercontent.com/u/56297224/UnitySumple2/Excel%E9%80%A3%E6%90%BA/excel%20sample.unitypackage

新型・一連のパッケージ
https://dl.dropboxusercontent.com/u/56297224/UnitySumple2/Excel%E9%80%A3%E6%90%BA/excel%20sample2.unitypackage

なお入力するExcelData.xlsや出力するExcelData.assetのパスは固定なので、変更しないように注意。


遊び方はこんな感じ

スクリーンショット 2013-06-27 23.20.36
ExcelData.xlsを開く。OpenOfficeやOfficeがあれば開ける。


スクリーンショット 2013-06-27 23.20.58
中身を書き換える。絵はOpenOffice


スクリーンショット 2013-06-27 23.21.06
UnityEditorに戻ると自動的にExcelData.xlsが再インポートされ、ExcelData.asstが出力される。以降、Excel.xlsが変更される度にExcelData.assetの中身を変更する。


スクリーンショット 2013-06-27 23.21.16
ScriptableObjectに流し込んだ図。入力不可なのはscriptableObjectのhideFlagsをHideFlags.NotEditableに設定しているため。
(ワークフロー的に簡単に上書き出来てしまう場合混乱するので、逆方向は無しにした)


スクリーンショット 2013-06-27 23.21.31
ScriptableObjectに流し込んだので、参照を与えるだけでゲームから読み込める。


ツィート数が2桁以上あったらもう少し詳しく書こうかな(チラ

UnityでExcel(xls)を使う Excel Data Reader - Read Excel files in .NET

excel?好きだよ。最高に幸福なツールですよね。

方眼紙は最高だし、お絵かきツールとしても好きだ。画像をD&Dで貼り付ければ簡単にクソ重い画像を添付できるし、複数のページに渡って管理もできる。

よく壊れる事に定評のあるバージョン管理機能だってあるし、メールベースでやり取りすれば自分と相手でブランチを(気づかぬ内に)分ける事も簡単だ。まあマージ出来ないけどね。

セルを結合したり分離したりすれば後々セルを整理する仕事を作ってくれるし、無駄に凝ったセル形状のせいで改修しにくいようにしてくれたり、印刷時に実際のレビューと印刷結果を調整する仕事だって増やしてくれる。

ハハハハ
市民、幸福は義務です


という事で、Unityでexcelを使う方法。
実際はxmlを吐き出して管理した方が簡単だしデータとして組み込めるので利便性も高いけど、一応出来るので紹介だけしておこうと思う。

うまくいくと、下のような感じになる。
スクリーンショット 2013-06-25 0.46.04
while-doの形は嫌いなのでendで数を合わせてる


スクリーンショット 2013-06-25 0.47.15
ちなみにMonoなのでMacでも動作する。


まず準備。
ココのページからexcel.dllをダウンロードしてUnityに入れるだけ。
dllはビルド済みなので本当に入れるだけ。おお簡単簡単。

後は下のコードのように書く。filePathはexcelへの相対パスを入れる。
(例:Assets/コピー〜data最新-修正版(2).xls)

ちなみにiOSAndroidでの動作は確認していない。絶対遅いし。
やるならエディタ拡張でデータを取得してscriptableObjectとかに突っ込む感じか。


追記
自分の環境だとxlsx読めなかった。

ScriptableObjectのhideFlagをリセット

ScriptableObjectはGameObjectと違い「ゲーム実行時」の情報を保持する。

しかし、ゲーム実行時はデータを更新してほしくない場合はHideFlagsにDontSaveを指定することで実行時のゲーム状態を保存しないようにも出来るらしい。
(ただし、インスタンスが即破棄される訳ではないので、その点に注意。逆を言えば、インスタンス更新したのに値が更新されていないケースは、dontSaveが指定されているかエディタ拡張で操作した後にEditorUtility.SetDirtyを呼んでいないかの可能性が高いと思う)

HideFlags
http://docs.unity3d.com/Documentation/ScriptReference/HideFlags.DontSave.html

本題だが、このHideFlagsはニュートラルの設定が一覧に無い。DontSaveを一度付けてしまうと戻せない、戻しにくい。

なので、こんな感じでニュートラルに戻してやる。

hideFlags = 0;

要するに、hideFlagsはどうもビット演算で管理しているみたいなので、0(何も設定していない)を投入すればリセットできるという理屈。