FC2ブログ
ヽ|∵|ゝ(Fantom) の 開発blog? ホーム »Unityオープンソースライブラリ
このページの記事一覧

【Unity】【C#】BMP をランタイムで読み込む  


 実は VRM Live Viewer には既に導入されているのだが、BMP を画像素材(テクスチャ)として利用したいこともあるだろう。実装当時、ググっても英語サイトしか出てこなかったので、需要は少ないのかも知れないが、探すのに苦労しないように備忘録として残しておく。

 今回紹介する方法は、オープンソースの BMPLoader を使う方法だ。

 以前「ランタイム時にファイルをドラッグ&ドロップして取得する」で紹介した「UnityWindowsFileDrag-Drop」の作者の Bunny83 さんの配布ライブラリで、とても簡単に扱えたので、その方法を書いておこう。


(※) Unity 2018.4.8f1 / Windows10(x64) で確認



■BMPLoader を導入する

 導入方法は簡単だ。以下の公開サイトへ行き、コピペで C# ファイルを作って欲しい。ページの一番下の方に「Raw Paste Data」という欄があるので、ここからコピーするのが簡単だろう。

BMPLoader.cs





■簡単なサンプルを作ってみる(基本的なコード)

 ググってみるといくつか出てくるので、以下などを参考にするのも良いだろう。

How to load a BMP file in binary?
How can I use a .bmp file and create a Texture in Unity at runtime?

 実際には BMPLoader.LoadBMP() はいくつかオーバーロードがあるので、利用方法によって使い分けるのも良いかも知れない。ここでは後述する「非同期ロードに対応してみる」に合わせた書き方となっている。定義をみて自分なりに書き換えるのも良いだろう。

●BMPLoadTest.cs(※名前は任意)
using System.IO;
using UnityEngine;
using UnityEngine.UI;
using B83.Image.BMP;

public class BMPLoadTest : MonoBehaviour
{
public RawImage image; //読み込み先(※インスペクタで UI を設定)
public string filePath = "c:/test/image/sample.bmp"; //※ファイルは任意

// Use this for initialization
private void Start()
{
var bytes = File.ReadAllBytes(filePath);
var loader = new BMPLoader();
//loader.ForceAlphaReadWhenPossible = true; // can be uncomment to read alpha
var bmpImage = loader.LoadBMP(bytes);
image.texture = bmpImage.ToTexture2D();
}

private void OnDestroy()
{
if (image.texture != null)
{
Destroy(image.texture);
image.texture = null;
}
}
}
#endif

 このサンプルではエラーのチェック等は省略しているので、あくまで全て必要なもの(ファイルとか)が揃っている場合であることを留意しておいて欲しい。

 とりあえず、BMP をロードして表示できたなら成功だ。





■非同期ロードに対応してみる

 とりあえず前述の基本的なコードでも十分なのだが、動作確認が取れたなら、ちょっと手を加えて非同期読み込みすると良いかも知れない。ただし、以下のコードは .NET 4.x 以降である必要がある。

●BMPLoadTest.cs(※名前は任意)
using System.IO;
using System.Threading.Tasks; //※追加
using UnityEngine;
using UnityEngine.UI;
using B83.Image.BMP;

public class BMPLoadTest : MonoBehaviour
{
public RawImage image; //読み込み先(※インスペクタで UI を設定)
public string filePath = "c:/test/image/sample.bmp"; //※ファイルは任意

// Use this for initialization
private async void Start() //※async を追加
{
var bytes = await Task.Run(() => File.ReadAllBytes(filePath)); //※Task で別スレッドで読み込み
var loader = new BMPLoader();
//loader.ForceAlphaReadWhenPossible = true; // can be uncomment to read alpha
var bmpImage = await Task.Run(() => loader.LoadBMP(bytes)); //※Task で別スレッドでロード
image.texture = bmpImage.ToTexture2D();
}

private void OnDestroy()
{
if (image.texture != null)
{
Destroy(image.texture);
image.texture = null;
}
}
}
#endif

 ファイルの大きさにもよるが、私が計測したところ、非同期にすれば約1.5倍くらいの速度で読み込める。もし、UniRx を使っているのなら、Task は UniTask にした方が良いだろう。

 ちなみに私が提供しているプラグインを使えば、Android でも BMP を読み込めた。実際にスマホで全天球ビューワを作ることも可能だ(これが VRM Live Viewer で実装されている)。

 ここでは簡単なサンプルなので Start() でやってしまったが、static なメソッドにしてしまえば、使い回しもできて非常に便利だ。その場合にはファイル名やファイル自体の存在チェック、非同期キャンセルのための CancellationToken など入れた方が良いだろう。Task.Run() は2回に分けてあるが、ファイル読み込み/テクスチャとしてロードするのに時間がかかることを考慮して、それぞれにキャンセルチェックをした方が良いと思う(きちんと実装すると結構長くなるため、今回は要点だけにした)。その辺りはご自由に(笑)。






(関連記事)
【Unity】【C#】ランタイム時にファイルをドラッグ&ドロップして取得する(Windows のみ)
【Unity】スマホで簡易360度(パノラマ, 全天球)ビューワを作る
【Unity】Androidのトーストやダイアログ、通知、音声認識、ハード音量操作など基本的な機能を使えるプラグインを作ってみた
【Unity】AssetStore版 FantomPlugin のセットアップ


関連記事
スポンサーサイト



category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: Unityオープンソースライブラリ  画像ファイル読み込み 
tb: 0   cm: --

【Unity】Unity2019.3 で Android / iOS ネイティブの構成が変わるらしい  


 Unity Asset Store にプラグインを出していることもあって、デベロッパーのメルマガで Unity2019.3 の大きな変更点が送られてきた。

 どうやら今までの Unity での Android / iOS ビルドの際のネイティブの構成が変わるらしい。

 まぁ、自分でプラグインなど作ったりしない場合はあまり関係ないと思うが、Unity2018.2 からは Android も Java コードをそのままビルドできるようになったので、ネイティブを使う人なら知っておいた方が良いだろう。

 詳細は公式のフォーラムを見た方が良いと思うが、例えば Android では 2019.3 で以下のような構成になるようだ。


Using Unity as a library in native iOS/Android apps


 また、Unity2019.3 からは今までと違って、ランチャーを挟んで本体の起動できるようだ。複数のアクティビティを使わないなら、あまり必要もないかもだが、例えば通常のアプリでの画面と Unity での 3Dモードで開くなど、今までより簡単にできるかも知れない。ただし『アンロードボタンは、単にアクティビティを破棄するのではなく、実際にアプリを終了します』とあるね。これも公式のフォーラムを見た方が良いだろう。


Integration Unity as a library in native Android app


 まぁ、見た感じ私の提供しているプラグインはそのまま動きそうな気がするが、確認が取れるまで、Unity2019.3 以降ではフィルタされるようだ(メルマガに書いてあった)。


 Unity の GUI も Flutter ライクのワークフローで開発できるパッケージも提供され始めたしね。UIWidgets は UIを1ドローコールで60fps以上の高効率でレンダリングできるらしいし、ネイティブのような画面遷移できるらしい。動画観てみると Unity とは思えない画面だね(笑)。


UIWidgets (Asset Store)
UIWidgets (github)
【Unity提供アセット】FlutterライクのワークフローをUnityで実現!強力なUIプラグインパッケージが新登場。60fps以上のレンダリング効率、クロスプラットフォーム対応。1ドローコールで描画する「UIWidgets」


 以上の情報からもネイティブ統合は今後強化されるかもね。





(関連記事)
【Unity】Unity2019 の StandardShader の処理が少し変わったらしいよ
【Unity】Unity2018.3.2 にアップグレードすると見た目がおかしくなることがある
【Unity】Android アプリでパーミッション(権限)要求をする
【Unity】IncrementalCompiler でのエラー:Unloading broken assembly Packages/com.unity.incrementalcompiler/Editor/Plugins/Unity.PureCSharpTests.dll, this assembly can cause crashes in the runtime
【Unity】Unity2018 でビルドエラー「CommandInvokationFailure: Gradle build failed.」が出る



関連記事

category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: Unityプラグイン  Unityオープンソースライブラリ 
tb: 0   cm: --

【Unity】【VRMLiveViewer】GLBで背景モデルを自作する  


 今回は、VRM Live Viewer で背景を自作したい人のために、GLB を使った簡単な素材作成法を書いておこう。これは実際にデモで使った素材の作り方そのものなので、同じようにやれば、そっくりそのままの背景モデルを作ることもできるだろう。



 GLB は汎用的な3Dモデルフォーマット GLTF と内部的に同じフォーマットである。簡単に言えば GLTF のアーカイブ方式が GLB と考えても良い。専用フォーマットではないため、VRM Live Viewer とは関係なく、色々なもので使える利点がある(例えば、Windows10のペイント3Dでも読み込める)。最近では「Vキャス背景」などにも大量にアップロードされているように、割と誰でも作れることもわかるだろう。

 実の所、VRMGLB と同じ GLTF を拡張したフォーマットだったりする。なので、.vrm を .glb に拡張子を変えるだけで使えるものもある。

 幸いにも Unity では UniVRM というオープンソースライブラリも無料で提供されているので、それを使えば誰でも簡単に GLB ファイルも作れる。公式にも GLB の説明は書いてあるので、一読しておくと良いだろう。今回はそれを実際にやってみたという内容だ。自作するときの参考にでもして貰えると嬉しい

glbファイルの作り方


(※) Unity 2018.4.0f1 / UniVRM 0.51.0 / Windows10(x64) で確認



■UniVRM のインポート

 今回は最終的に GLB でファイルを出力するために UniVRM というライブラリを利用しよう。Release ページへ行って、.unitypackage をダウンロードしよう。ここでは「UniVRM-0.51.0_1b36.unitypackage」と「UniVRM-samples-0.51.0_1b36.unitypackage」の2つ(※バージョンは掲載時点なので、置き換えて下さい)をダウンロードして欲しい。これはライブラリ本体とその利用サンプルだが、-samples の方に GLB エクスポートなどの機能も含まれているので、どちらも必要になる。インポートする順は本体→サンプル(-samples)の順の方が良いだろう(逆だとエラーが出る)。

UniVRM (Release)

 Unity 自体が初めての人は「Unity Hub」をダウンロードして、「インストール」から最新のバージョンをダウンロードすると良い。

Unity ダウンロード



 メニューに「VRM」が追加されていれば完了だ。実際にこれだけで、例えばシーンに1個 Cube を置いて、それをヒエラルキーで選択したまま、メニューから Export すれば glb ファイルが作れる。



 まぁ、今回は背景を作ってみるというテーマなので、アセットストアから無料素材を落として、それを glb にすることを練習にやってみよう。試してみたら、少しばかり注意すべき点もあったので、その辺りも書いておこう。



■アセットストアから素材のインポート

 今回は「Grass Road Race」という無料素材をアセットストアからダウンロードして使ってみよう。

 使う素材は何でも良いが、注意点としては Terrain の地形より、なるべく単体のメッシュで構成された素材の方が良いだろう。理由は編集しやすい事もあるが、Terrain だとそのままエクスポートできず、変換が必要となるからだ。またその変換されたメッシュはポリゴン数などが大きくなってしまうため(ツールによっては間引きできるが、感じが変わってしまう)、アプリなどに利用すると重くなってしまう傾向がある。その辺りの工夫も後述しておこう。


 Unity をあまり使ったことない人に説明しておくと、アセットストアとは Unity で直接使える素材(3Dモデルだけでなく、アニメーションやスクリプトなども含む)を購入できる専用ストアで、また自分で販売することもできる(私も Android のプラグインを無料で配布している)。無料のものも結構あるので(検索で $0 にすれば無料だけを検索できる)、色々試してみるのにも良いだろう(Unity 上からは Ctrl + 9 で検索すると良い)。


 インポートしたら準備は完了だ。次は素材を GLB 用に編集してみよう。



■GLB 用に素材を編集する(島を作る)

 まずはインポートした「GrassRoadRace」フォルダ以下のサンプルシーン「Scene_GrassRoadRace」を開いてみよう。元のシーンを残しておきたいなら、Ctrl + D で複製を作って編集しても良い。



 地形は自由に作っても良いが、私が実際にやった方法と、ちょっとした注意点を書いておこう。

 先に概略を挙げておくと、使うシェーダとアニメーション、メッシュの結合などである。特にシェーダに関しては公式にもあるように『Standard もしくは Unlit/Color, Unlit/Texture, Unlit/Transparent, Unlit/Transparent Coutout, UniGLTF/UniUnlit』となっている(掲載時点:UniVRM0.51.0)。ここでは基本的に Standard シェーダのみを使う

 完成形は1つの孤島を作ってみた。大きさは 10x10 m くらいだろうか。Unity の Scene ビューでは薄いグリッド線が見えると思うが、これが 1m となっている(拡大してるとき)。わかりずらければ Cube が 1x1x1 m なので1つ置いて基準にするのもいいだろう。最終的に VRM Live Viewer で使うなら、Capsule(高さ[Height]を 1.5m [身長]にしておく)を人型として目安にするのも良い。




 島を構成するオブジェクトは「Ground02」「Ground03」「Ground04」の3つだ。検索すればいくつか出てくるが、1つずつ取り出して、空の GameObject(ここでは「island_base」としている)に入れよう。Position は一旦 (0, 0, 0) にしてから、ぐるりと周りからみて穴が開かないように、Position を配置して欲しい。参考に値を書いておくと、Ground02: (0, 0, 0), Ground03: (0, 0, -3.809998), Ground04: (0, 0, 3.809998) となっている。調整中は邪魔なので Track は非表示にした方が良いだろう。




 また今回は島にフェンスを付けないので、ここで削除してしまおう。Unity 2018 以降を使ってるなら、各素材を選択して、「Unpack Prefab」(Unity2017 以前は「Break Prefab」だった気がする)した後で、「Fence」を削除しよう。




 次にシェーダの設定を変更しておこう。初期の状態では「Mobile/Diffuse」になってると思うが、これを全て「Standard」にしておいて欲しい。すると見た目が暗くなると思うが、「Albedo」を完全な白に、「Smoothness」を0にすれば、少し明るくなる。使えるシェーダについては公式に書いてあるので、参照して欲しい。





 最後に島全体の大きさと位置を決めておこう。親オブジェクト(island_base)をヒエラルキーで選択して、Transform を適当に調整すれば良い。




 木の配置も基本的には同じやり方だ。非表示にしている Track の中から「GroundIsland」を取り出し(Scale が (1, 1, 1) のものを選ぶと良い)、空のオブジェクト(tree_base としている)の中に入れよう。一旦全ての Position を (0, 0, 0) にした方が良い。



 島のときと同じように、「Unpack Prefab」をした後で、「Grass」と「PalmTree」を選択し、シェーダを設定して欲しい。シェーダはマテリアルごとの設定となるので、面倒ならマテリアルの方をプロジェクトビューで全て設定しても良いだろう。




 シェーダを設定したら、木を複製(ヒエラルキー上で Ctrl + D)して3つにしよう。Position は適当で良いが、参考値としては、(0, -1.108, -4), (3.4, -1.108, -4), (-3.4, -1.108, -4) となっている。



 3つ適当に並べたら、親オブジェクトである「tree_base」を複製(Ctrl + D)して、180度回転しよう。これで簡単に6つになった。少しだけ Z の値を調整している。値は適当で良い。




 後は両サイドに1つずつ木を足しておこう。空のオブジェクト(tree_base_side としている)を作って、tree_base, tree_base (1) の中の GroundIsland (2) をそれぞれ複製して(Ctrl + D)、tree_base_side 内に移動し、位置と回転を調整している。値は適当で良い。回転は木の根本にある草が島の内側に向くように調整すると良いだろう(裏からだと見えなくなるため)。




 最後にこれら全部の素材を1つにまとめる空オブジェクトを作り、その中に移動しよう。Z を動かしたのは原点から見て中心あたりにしたかったからだ。他のアプリなどで読み込むときのためにも、なるべく中心がワールド座標の原点となるように配置しておくと良い

 これで一応、島は完成だ。






■メッシュを結合する

 この操作は必須というわけではないのだが、特に今回のような複数の素材を組み合わせて作るものなどは、メッシュを結合をやっておくと良いだろう。その理由はテラシュールさんのブログを見て貰えばわかると思うが、単純に動かない物体などはなるべくまとめてしまう方が、利用時に軽くなるからだ。

Unityのシーン上に配置したモデルを結合する

 ここでは簡単にやり方を書いておこう。記事を読んでいくとソースコードが掲載されているが、github にも公開されているので、こちらから zip で落とすのが楽だろう(「Download ZIP」ボタンを押す)。

MeshCombiner.cs

 「MeshCombiner.cs」をダウンロードしたら、適当にフォルダでも作って、プロジェクトにインポートして欲しい。

 たぶん現在の Unity のバージョンではエラーが出ると思うが、エラーが出たら Console でダブルクリックし、エディタを立ち上げて欲しい。エラーの箇所は古い書き方なだけなので、今の書き方に修正するだけで良い。具体的には以下のように修正する。



●25行目(エラーが出てる行)を以下のように修正する
var mat = mesh.GetComponent<Renderer>().sharedMaterial ;


 修正してエラーが出なくなったら、MeshCombiner を完成した背景モデル(ここでは Island)にアタッチして欲しい。アタッチしたら、生成先となる空のオブジェクトをヒエラルキーで作成し、それを MeshCombiner の Generated Object にドラッグ&ドロップして設定する。



 Generated Object を設定したら、MeshCombiner の 右端にある歯車アイコンを押して、メニューから「Export」しよう。しばらくすると、元オブジェクト(Island)が無効化され、代わりにメッシュが結合されたオブジェクトが生成される。名前は後でわかり易いように変えておくと良い。




 特に見た目が変わってないので、わかりずらいかも知れないが、プロジェクトビューで見てみると、結合された新しいメッシュが生成されていることがわかる(物によっては少しテクスチャが元と違う感じになることもある。マテリアルごとにまとめられるらしい)。



 ここまででも、出来上がった背景オブジェクトをヒエラルキーで選択して、メニューから「VRM>UniGLTF-1.28>Export」すれば glb
出力できる。試しに VRM Live Viewer で読み込んで見ても良いだろう(ウィンドウに出力ファイルをドロップすれば良い)。





■海を作る

 まずは、海(Wave)を非表示にした Track の中から取り出そう。そしたら、一旦 Position を (0, 0, 0) にし、ヒエラルキーで Wave を選択した状態で「Unpack Prefab」をし、シェーダを Standard にして値を設定する。これらは今までと同じやり方だ。




 海を配置すると、原点から Z 方向に伸びていることがわかる。今後アニメーションで利用するためにも、ここでちょっと工夫しておこう。島を作るときに使った MeshCombiner を Wave にアタッチし、Position Z を -188 にして欲しい。また、MeshCombiner の出力先となる空のオブジェクト(Sea としている)を作り、設定する。そしたら歯車アイコンから Export してメッシュ結合しよう。




 実はここで MeshCombiner を使ったのはメッシュの基準を原点にしたかっただけだったりする(笑)。なので、自分で Plane を作ってマテリアルを貼り付けるのもアリだと思う。また、スケールを1にする目的もある。こういう使い方もあると覚えておくと、素材作りに役に立つかも知れない。

 あと、結合すると static(静的オブジェクト=動かないオブジェクト)となるので、チェックを外して欲しい。外そうとするとダイアログが出るが、これは「子要素も外すか?」という質問なので、「Yes」の方を選択して欲しい。これは後でアニメーションさせたいので、そのための準備だ




 最後に全体を1つにまとめる空オブジェクト(root としている)を作って、島(Island)と海(Sea)をその中に入れよう。また、少し海の Y 座標を -1.5 下げて、島が浮いている感じを出してみる。




 これで背景モデルの全体像は完成だ(カメラは少し近づけている)。もちろん、ヒエラルキーで root を選択したまま、メニューから Export すれば glb ファイルが作れる。





■アニメーションをする

 ここまでで、GLB が一応できたと思うが、ちょっと工夫して海の水の流れっぽいアニメーションを作ってみよう。と言っても、ここでやる方法はあくまで GLB 仕様のための方法で、アニメーションの例としては良い使い方というわけではない(大抵はテクスチャの UV 座標を移動する方が多いと思うが、スクリプトが必要なため)。しかし基本は同じなので、実際には自由にアニメーションを付けてみると良いだろう。

 ここで GLB の仕様を確認してみると『一番親のオブジェクトに付けてください。回転はQuaternionのキーフレームを打ってください。移動・回転・拡縮に対応しています。BlendShapeは未対応』とあるので、この場合、アニメーションは「root」にアタッチすれば良いことがわかる。

 まずはヒエラルキーの「root」を選択し、Ctrl + 6 からアニメーションビューを表示しよう。後述の「Create」でファイルが作成され、必要な Animator が自動でアタッチされる。




 アニメーションの使い方・作り方などの詳細は公式のマニュアルを読んで欲しいが、ここでは概要だけを簡単に書いておこう。あくまでも大雑把にそれっぽく作る例なので、クオリティ云々は度外視して欲しい(笑)。

アニメーション
新しいアニメーションクリップの作成

 アニメーションビューが開いたら、まずは「Create」ボタンでアニメーションクリップのファイルを作ろう(sea_move としている)。ファイル名は適当で良い。



 ビューでは「Add Property」を押し、海の Transform:「Sea>Transform>Position」を開き、(+)ボタンを押す。



 初期状態では1秒後にキーフレームが打ってあるので、それを削除しておく。



 海の移動では Z 方向だけを使うので、最初のフレーム(0)には Z:100 を、フレーム:18000(5分後)には Z:-100 を、フレーム:36000(10分後)には Z:100 にキーフレームを打っておく。一番簡単な方法は、ビューのプレイボタンの右にあるテキストボックスにフレーム数を入れ、そのすぐ左下にあるキーフレーム追加ボタン(菱形に+があるアイコン)を押して、プロパティの Position.z に直接値を入力することだ。

 ちなみにこれは、海が前後にゆっくり5分かけて移動することを意味する。



 また、プレビューで再生してみるとわかるが、初期状態ではイージングが入っているので、だんだん早く移動するようになっている。このままでも別に構わないが、動きが確認しずらいので、とりあえずビュー下にある「Curves」を押して、動きを直線的にしてみよう。



 編集方法は各ポイントを右クリックし、すべての Tangent を「Linear」にしておく。まぁ、往復する瞬間は急激なターンとなるが、その辺が気に入らなければ、カーブを付けても良いだろう(※だが、GLB では効いてない気がする)。



 最後に、作ったアニメーションクリップ(ここでは sea_move)をプロジェクトビューで選択し、「Loop Time」のチェックをオンにし、アニメーションをループ再生にしておこう。



 試しにエディタで再生してみるのも良いだろう。ただ、デモのカメラをそのまま使ってるなら、「Camera Move」はオフにし、カメラの Transform を島の近くに移動した方が良いだろう。上手く行ってれば、海が流れるように見えるハズだ(ただ移動してるだけだが(笑))。





■GLB ファイルを出力する

 ここまでで本当に完成だ。後は冒頭にも書いたように、ファイルをエクスポートするだけだ。本当にお疲れさま(笑)。

※他者の素材を利用した場合は、あくまで学習用途に限定しておき、配布などはしない方が良いでしょう。



 VRM Live Viewer で見てみるにはウィンドウにドロップするのが簡単だろう。あとは色々工夫して素材作りを楽しむのも良いと思う。Unity2018 以降を使うなら、ProBuilder で1から作っても良いかも。観た人があっと驚くようなシーンを作ってみたいね(笑)。

ProBuilderでモデリング入門







(関連記事)
【Unity】VRM(VRoid)をライブステージで踊らせるアプリを作ってみた
【Unity】VRoid(VRM)をインポートして動かす
【Unity】【C#】Android で VRM(VRoid)を動的に読み込む
【Unity】AssetStore版 FantomPlugin のセットアップ
【Unity】Androidのトーストやダイアログ、通知、音声認識、ハード音量操作など基本的な機能を使えるプラグインを作ってみた


関連記事

category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: Unityオープンソースライブラリ  VRM  VRoid  VRMLiveViewer 
tb: 0   cm: --

【Unity】【C#】アセットバンドルのキャッシュを調べて不要なものを消す  


 もう随分 AssetBundle Manager を触ってなかったのだが、ちょっと利用する機会があったのでメモ。

 どうやら Unity2017 以降にはキャッシュの操作もできるようになったみたいなので、キャッシュの存在確認や不要なキャッシュを簡単に削除できると良いと思った。

 この AssetBundle Manager はUnity5 時代のもので、もうアセットストアからは落とせないみたいだが、まだお世話になってる人のためにも機能追加案を書いておこう。他のツール使ってるなら必要ないかもだが、同じような考え方なら流用もできるだろう。


(※) Unity2018.3.9f1 / Windows10(x64) で確認



●マニフェストからハッシュを取得
//マニフェストからハッシュを取得
static public Hash128 GetAssetBundleHash(string assetBundleName)
{
return m_AssetBundleManifest.GetAssetBundleHash(assetBundleName); //※先にマニフェストをロードしておく必要あり
}

 この関数はレガシーな AssetBundle Manager を基にしてるので注意(スコープや書き方も合わせている)。

 これは元からある AssetBundleManifest.GetAssetBundleHash を少し簡単にしただけのものなので、あまり説明はいらないだろう。このハッシュは実際にマニフェストに書かれているもので、テキストエディタなどで「~.manifest」を開けば、それぞれの「AssetFileHash」に対応していることがわかる。もう結構古い記事になるがテラシュールさんの記事に詳しく書いてあるので、参考資料として載せておこう。

AssetFileHashとTypeTreeHashは、AssetBundleの更新判定
AssetBundleManifest.GetAssetBundleHash



●アセットバンドルがキャッシュに存在しているか?(url と hash を用いる)
//アセットバンドルがキャッシュに存在しているか?
static public bool IsExistCaching(string assetBundleName)
{
var url = BaseDownloadingURL + assetBundleName;
var hash = GetAssetBundleHash(assetBundleName);
return Caching.IsVersionCached(url, hash);
}

 この関数もレガシーな AssetBundle Manager を基にしてるので注意(スコープや書き方も合わせている)。GetAssetBundleHash は前述したものだ。

 なぜだかわからないが、この関数はわりと昔からあって(Unity5 の時代からあったらしい?)、マニュアルにも載ってるバージョンとそうでないバージョンがある。

 IsVersionCached(string url, int version) の方は Obsolute(廃止予定)だし、version の指定はどちらかというと、アセットバンドル全体のバージョンという感じで、個々のアセットバンドルの差分としては使いづらいんだよね(この version は WWW.LoadFromCacheOrDownload [obsolute] や UnityWebRequestAssetBundle.GetAssetBundle などの引数に当たる)。なので、ハッシュの方を使いたいことが多い。まぁ、url 指定なので少し使いづらいが…。

 また、ハッシュと任意の名前を用いることもできる。ここでは名前をアセットバンドル名としておくと、以下のようなものも作れる。

●アセットバンドルがキャッシュに存在しているか?(url と name を用いる)
//アセットバンドルがキャッシュに存在しているか?
static public bool IsExistCaching(string assetBundleName)
{
var hash = GetAssetBundleHash(assetBundleName);
var cab = new CachedAssetBundle()
{
hash = hash,
name = assetBundleName,
};
return Caching.IsVersionCached(url, hash);
}

 こちらの方が使いやすいかも知れない。url をキーとしてないので、移動しても使える。

 ついでに色々資料も載せておこう。

キャッシュの存在確認
Caching.IsVersionCached
WWW.LoadFromCacheOrDownload [obsolute]
UnityWebRequestAssetBundle.GetAssetBundle



●現在のハッシュ以外のキャッシュを消す
//現在のハッシュ以外のキャッシュを消す(※使うタイミングに注意)
static public bool ClearOtherCaching(string assetBundleName)
{
var hash = GetAssetBundleHash(assetBundleName);
return Caching.ClearOtherCachedVersions(assetBundleName, hash);
}

 この関数もレガシーな AssetBundle Manager を基にしてるので注意(スコープや書き方も合わせている)。GetAssetBundleHash は前述したものだ。

 これは割と最近(Unity2017.1 以降?)にできてたらしい。調べていたら出てきたので、試してみたら上手く行った。実行は同期的なのでタイミングには気をつける必要があるが(まだ古い使用中アセットがあった場合、途中破棄されるわけで)、他にも削除する方法はあるみたいなので、色々やってみるのも良いかも知れない。また、資料には「デフォルトで150日間で期限切れ」ともあるね。以下に記事も載せておこう。

[Unity 2018.2] AssetBundleのキャッシュを完全に理解する
期限切れによる削除
Caching.GetCachedVersions



 まぁ、この AssetBundle Manager 自体は旧時代のものなので、これからも使うなら少し書き直した方が良いかも知れない。WWW よりも UnityWebRequest の方がパフォーマンス良いと聞いたこともあるし、実際に書き換え例なんかもあるので、自分でやってみると良いかも(Unity2019 には Addressable Assets というものも出てくるらしいしので今更だが(笑))。

AssetBundleManagerのwwwをUnityWebRequestに変えて、さらにキャッシュの古いバージョンを削除してみる






(関連記事)
【Unity】【C#】AssetBundleManager を WebGL で使う・エラー対処法
【Unity】【C#】Addressable Assets でキー(アドレス)の存在(登録)を調べる


関連記事

category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: Unityライブラリ  Unityオープンソースライブラリ 
tb: 0   cm: --

【Unity】Firebase のプッシュ通知と FantomPlugin の共存(Firebase と他のプラグインの共存方法)  


 ちょっと最近 VRM Live Viewer に構いっきりで(笑)、FantomPlugin の更新の方が滞っているのだが、Android 8.0 以降では通知システムも変わってしまったので、試しに Firebase のプッシュ通知をオーバーライドできるかやってみた。結果はそれほど難しく無く可能だったので、細かい部分はカスタマイズした方が良いと思うが、導入もできると思う。あくまで簡単な例となるが、FantomPlugin と Firebase の共存の方法を提供しておこう。

 ただ、この機能は Unity2018.2.x 以降のプロジェクト内で Java をプラグインとして扱えるようになったおかげで使えるようになったものなので、必要であれば、以下の記事も参照して欲しい。

【Unity】【C#】プロジェクト内で Android(Java)プラグインをビルドする


(※) Unity2018.3.5f1 (Unity 2018.2 以降) / Firebase SDK 5.5.0 / Windows10(x64) で確認



■プラグインの導入

 大まかには Firebase SDKFantomPlugin の2つを用意することになる。といっても、ここではオーバーライドするプラグインの例に FantomPlugin を使っているというだけで、考え方さえわかれば、他のプラグインに Firebase を利用することも可能だろう。



●Firebase SDK のインポート(掲載時点 SDK ver.5.5.0)

 Firebase のプッシュ通知を利用するには、公式から配布されている Unity 用のパッケージを導入する必要がある。以下のページに「SDK をダウンロード」というボタンがあるので、クリックして zip をダウンロード→解凍して欲しい。

Unity プロジェクトに Firebase を追加する


 zip を解凍すると、「dotnet4」というフォルダがあるので、その中から「FirebaseMessaging.unitypackage」をインポートしよう。これには Firebase からプッシュ通知を受け取るアクティビティやマニフェストファイル、API などが含まれている。初回のインポートでは依存関係のライブラリを自動導入するので、結構時間かかるかも知れない(※Build Target が Android になってない場合はここでやっておくと良い)。また、「dotnet3」にも同じものが入っているが、これは .NET 3.x 時代のもので、Unity2018 ではデフォルトで .NET 4.x となっているので、ここでは不要だ。

 Resolver(依存関係の解決)が終わったら、大量のファイルが「Assets/Plugins/Android」に配置されていると思う。Firebase を既存のプロジェクトに使うだけなら、ここにある「AndroidManifest.xml」はあまりいじる必要はないが(だいたい自動でやってくれる)。他のプラグインと共存するには少し手を加える必要がある。その辺りは後で説明しよう。



●FantomPlugin のインポート

 とりあえず今回はアセットストア版の「FantomPlugin (Android Native Dialogs and Functions Plugin)」(※長いので略してるだけ(笑))を使って説明しよう。Google Drive 版を使っている人でも基本的には同じなので、パス名などを置き換えてもらえばできると思う。

 より詳しいセットアップは「AssetStore版 FantomPlugin のセットアップ」の記事にも書いてあるが、簡単な方法としてはエディタ上で [Ctrl+9] でアセットストアを開き「Android Native Dialogs and Functions Plugin」を検索すれば、すぐに出てくると思うので、とりあえずダウンロード→インポートして欲しい。





■FantomPlugin オーバーライド用 Acrivity の導入

 インポートが終わったら、もう1つプロジェクトに追加して欲しいものがある。それは先ほど保留したAndroidManifest.xml」 に関わる問題でもある。というのは Firebase SDK のインポート で作られたマニフェストファイル(AndroidManifest.xml)は Firebase 専用となっている。この辺りの説明は少し難しくなってしまうのだが、なるべく簡単に説明すると、この「Firebase 専用のものをオーバーライドすることにより、他のプラグインの機能を共存してしまおう」ということだ。そのオーバーライドするのに必要な Activity を用意した。そのうち、アセットストア版にも出すつもりだが、とりあえずは先行配布としてこれを使って欲しい。


 ダウンロードして zip を解凍すると「Firebase」フォルダに「OverrideFantomPluginOnFirebaseMessagingActivity.java」というのが入っていると思う。これは現在使われている「FantomPlugin」と同じもので、Unity2018.2 のプラグイン用の Java コードをプロジェクト内でビルドするために作ってみたものだ(内容的にはプラグイン「fantomPlugin.aar」の内部に入ってる「FullPluginOnUnityPlayerActivity」と全く同じ)。


 また、「AndroidManifest_FirebaseMessaging.xml」というのも入っているが、これは Firebase の「AdnroidManifest.xml」に「OverrideFantomPluginOnFirebaseMessagingActivity」をオーバーライドするように修正したものだ。Firebase のデフォルト設定に追加しただけのものなので、必要あれば編集した方が良いかも知れない。

 これらをプロジェクトのプラグインルート「Assets/Plugins/Android/」以下に置いて欲しい。ここに Java ファイルを置いておけば Unity が自動でビルドしてくれる(Build System が「Gradle」のときのみ[※Unity2018 はデフォルト])。

 また、元の「AndroidManifest.xml」はリネームして「AndroidManifest_old.xml」とでもしておき、「AndroidManifest_FirebaseMessaging.xml」を「AndroidManifest.xml」にリネームすると、オーバーライドが有効になる


 この辺りの内容は少し難しくなるので、簡単に説明にしておくと、「UnityPlayerActivity(Unity)継承→ MessagingUnityPlayerActivity(Firebase)継承→ OverrideFantomPluginOnFirebaseMessagingActivity(FantomPlugin)」のようにオーバーライドされていることになる(※つまり自作するときは同じように、競合しないようなオーバーライドする Activity を作れば良い)。

 必要なら参考資料を載せておこう。ダウンロードした zip の中の「Default」フォルダがあると思うが、その中にある「OverrideFantomPluginOnUnityPlayerActivity.java」はデフォルトの「UnityPlayerActivity」を継承している。Firebase のオーバーライドと同じように継承するものを変更すれば、他のプラグインもオーバーライドできるかも知れない。

UnityPlayerActivity Java コードの拡張
Activity
アプリ マニフェスト



■Firebase の準備

 アプリ方の準備はだいたい終わったので、次のプッシュ通知を送信する Firebase自体をセットアップしよう。

1.Firebase をまだ利用してない人は、まずは登録しよう。といっても Google アカウントを持っていれば、サイトに行けばすぐに新規登録できると思う。登録完了したら、いつでも画面の右上あたりにある「コンソールへ移動」があるので、プロジェクト管理へ移動できる。


2.コンソール(「Firebaseへようこそ」)へ来たら、プッシュ通知を利用するプロジェクトを作成しよう。「+プロジェクトを追加」を押して、プロジェクト名などを任意に入力し、「プロジェクトを作成」ボタンを押せば良いだけだ。完了したら、プロジェクトへ移動しよう。



3.初回の場合、プロジェクトにはアプリが追加されてないので以下の画面が出ると思う。今回は Android のプラグインをオーバーライドする実験なので、Android のアイコンを押そう。



4.「アプリの登録」の「Android パッケージ名」は Unity の Identification と合わせておく必要がある(※以下のアプリIDは例なので、自分のアプリのIDに置きかえる)。Unity の PlayerSettings(File>Build Settings...>Player Settings...>Other Settings>Identification)を開いてコピペすると良い。ここが1文字でも間違ってたら、通知は届かないので注意しよう。



●Unity 側

※FantomPlugin を使う場合、Android 4.2 以上にする必要がある。


5.これら Firebase の設定を Unity に認識させるために、設定ファイル「google-services.json」をダウンロードしておく必要がある。このファイルは Unity の Assets 直下に置くことで反映される(ID の紐づけ)



●Unity 側


6.次の「Firebase SDK の追加」は Unity の場合、自動でやってくれるので必要ない。



7.最後の「アプリを実行してインストールを確認」はスキップしてしまって良いだろう。





■アプリをビルドする

 これまでの準備が整ったらアプリをビルドしてみよう。注意すべき点は、「OverrideFantomPluginOnFirebaseMessagingActivity.java」「AndroidManifest_FirebaseMessaging.xml(AndroidManifest.xml)」「アプリのID(Android パッケージ名/Identification)」「google-services.json」だ。結構大変だが、置く場所なども含めて確認して欲しい。

 確認が取れたら、ビルドするシーンは何でも良いが、FantomPlugin のデモなら、「FantomPlugin/Demo/Scenes/」以下に置いてある。それらを「Build Setting>Scenes In Buildに追加し、「Player Settings...」で「Minimum API Level」が 4.2 以上(※これは FantomPlugin の仕様。できれば 5.0 以上の方が良いかも知れない)になってればOKだ。ビルドして一度起動してみよう。また、今回は通知を受信する実験をするだけなので、アプリはすぐに終了して構わない。







■Firebase からプッシュ通知を送る

 ここまででの手順が間違ってなければ、既に Firebase からプッシュ通知の送信ができるようになっている。Firebase のコンソール へ行き、左のメニューから「Cloud Messsaging」へ移動しよう。初回なら「Send your first message」のボタンが出るので、それを押すとメッセージを作成することができる。



1.通知の作成画面では任意にテキストを入力して行こう。気をつけて欲しいのは既にリリースされているアプリの場合、適当に入力したものがユーザーに届いてしまうことである。その辺は自己責任で(笑)。



2.一番重要なのは、このターゲットのアプリ(ID)だ。ここを Unity のアプリの Identification と同じにすることによって、そのアプリ用の通知として送られる。間違えないようにしよう(Android / iOS などでも分別できる)。



3.以降の「スケジュール設定」は「Now」(今すぐ)で、「コンバージョンイベント」はデフォルトで良いだろう。「その他のオプション」では「Android 通知チャンネル」という項目があるが、これは Android 8.0 以降の「通知チャンネル」の機能で、通知ごとに種類を分別できるようにするものだ(例えば「お知らせ」とか「更新情報」とか、別々に通知のオン・オフできるようにするため)。Android 8.0 より前の機種では分別はされない。

Android O(APIバージョン26)のPush通知



4.最後の「メッセージの再確認」では「公開」ボタンを押すと即送信されるので(スケジュールで「今すぐ送信」(Now)の場合)、間違いがないか確認してから押そう。ユーザーに飛んでいってしまうので、もう取り消せない(笑)。



5.履歴が表示されていれば、送信完了だ。通信状態・サーバー状況などによって、タイムラグが出ることもあるが、成功していればおおよそすぐに通知が来ると思う。実機で確認してみよう。





※アイコンは Unity で設定したものが表示される(空だと Android のデフォルトアイコンになる)






(関連記事)
【Unity】【C#】プロジェクト内で Android(Java)プラグインをビルドする
【Android】【Java】パーミッションの付与(許可)のチェックと要求をする
【Unity】Androidのトーストやダイアログ、通知、音声認識、ハード音量操作など基本的な機能を使えるプラグインを作ってみた
【Unity】AssetStore版 FantomPlugin のセットアップ


関連記事

category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: Unityライブラリ  Unityプラグイン  Unityオープンソースライブラリ  Firebase  FantomPlugin 
tb: 0   cm: --


プロフィール

Social

検索フォーム

全記事一覧

カテゴリ

ユーザータグ

最新記事

リンク

PR