キャッシュをダウンロード
ゲームを実行する際に追加でダウンロードしたデータの事を「キャッシュ」と呼びます
Google Playでは100MB以下のAPKファイルでないとアップロードできないので
キャッシュで個別にデータをダウンロードする事になります
キャッシュを使う場合はAssetBundleと言う形式を使います
今回は画像をキャッシュする方法を説明します
■AssetBundle作成用のスクリプトを用意してAssetBundle作成 編
1. Unityを起動、プロジェクト作成
プロジェクトは "AssetBundleBuild01" としました
2. 画像を選択し、Inspectorを見ると下の方にAssetBundleという項目があります

ここを選択すると、項目が表示されるので「New」を選択し、AssetBundleの名前を入力します。
今回は "asset_pack01" という名前にしました

なお、大文字は使えないようです
3. AssetBundle作成用のスクリプトを用意します。
今回は Assets フォルダの下に "Scripts/Editor"
という階層のフォルダを作成し、"AssetBundleBuild.cs" というスクリプトを作成しました。

スクリプトの中身は下記になります。
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
public class AssetBundleBuild
{
[MenuItem("Expansion/Build AssetBundleData")]
public static void Build()
{
string
assetBundleDirectory =
"./AssetBundleData"; // 出力先ディレクトリ
string
AssetBundleBase = "";
// 出力先ディレクトリが無かったら作る
if
(!Directory.Exists(assetBundleDirectory))
{
Directory.CreateDirectory(assetBundleDirectory);
}
// AssetBundleのビルド
#if UNITY_STANDALONE_WIN
BuildPipeline.BuildAssetBundles(assetBundleDirectory,
BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows);
#endif
#if UNITY_ANDROID
BuildPipeline.BuildAssetBundles(assetBundleDirectory,
BuildAssetBundleOptions.None, BuildTarget.Android);
#endif
#if UNITY_IOS
BuildPipeline.BuildAssetBundles(assetBundleDirectory,
BuildAssetBundleOptions.None, BuildTarget.iOS);
#endif
//
AssetBundleの名前 ハッシュ サイズを纏めたデータを作る
string path =
"AssetBundleData/";
List<string>
files = new List<string>(Directory.GetFiles(path, "*.",
SearchOption.AllDirectories));
files.RemoveAt(files.IndexOf(path + "AssetBundleData"));
// jsonを保存
File.WriteAllText(path + "AssetBundleData.json", "");
// アセットバンドルのロード
AssetBundle ab =
AssetBundle.LoadFromFile(path + "AssetBundleData");
AssetBundleManifest
Manifest =
ab.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
// アセット情報を取得
for (int i = 0; i
< files.Count; i++)
{
// ハッシュ値の取得
Hash128 Hash =
Manifest.GetAssetBundleHash(Path.GetFileName(files[i]));
// ファイルサイズの取得
FileInfo file = new FileInfo(files[i]);
long size = file.Length;
// 文字列に登録
AssetBundleBase = Path.GetFileName(files[i]) + "/" + Hash + "/"
+ size;
// jsonに書き込み
File.AppendAllText(path + "AssetBundleData.json",
AssetBundleBase + "\n");
// 余分なファイルを削除
File.Delete(files[i] + ".manifest");
}
// 余分なファイルを削除
File.Delete(path +
"AssetBundleData");
File.Delete(path +
"AssetBundleData.manifest");
// ビルド終了を表示
EditorUtility.DisplayDialog("アセットバンドルビルド終了",
"アセットバンドルビルドが終わりました", "OK");
}
}
5. 作成用のスクリプトを実行します。
さきほどのスクリプトを追加するとUnity画面上部のメニュー内に「Expansion」が追加されているので、「Expansion」→「Build
AssetBundleData」を選択して下さい

成功しているとプログレスバーが表示され、その後に「アセットバンドルビルドが終了しました」というウィンドウが表示されます

6. Unityのプロジェクトを作成した場所をエクスプローラー等で開きます。
"AssetBundleData"
というフォルダが作成されており、フォルダの中を見るとAssetBundle用のデータが作成されているはずです


AssetBundle用のデータが作成されていれば成功です
元の画像は削除しても構いません
■作成したAssetBundleをネットワーク環境で読み込み 編
1. 作成したAssetBundleを全てサーバーにアップロードします
今回はDropboxを使用します
2. 読み込み用のスクリプトを用意します
Assets フォルダの下に"Cache.cs" というスクリプトを作成しました
スクリプトの中身は下記になります
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
public class Cache : MonoBehaviour
{
// データが保存されているWebサイトアドレス
public string BaseURL;
public string DataURL;
// アセットバンドル名
public string AssetBundleName;
// アセットバンドルデータ
public static List<string[]>
AssetBundleData = new List<string[]>();
private TextAsset LoadFile;
AssetBundle AssetData;
public List<Sprite> AllImage = new
List<Sprite>();
public Image image;
IEnumerator Start()
{
// キャッシュ削除
//Caching.ClearCache();
// キャッシュの場所
Debug.Log(Caching.currentCacheForWriting.path);
// オンライン状態ならダウンロード
if
(Application.internetReachability !=
NetworkReachability.NotReachable)
{
// Jsonデータを読み込み
yield return StartCoroutine(JsonDownload());
// キャッシュを読み込み(Falseにするとサイズだけ取得)
yield return StartCoroutine(CacheDownload(AssetBundleName,
true));
}
// データを読み込み
Load();
}
// Jsonデータの読み込み
IEnumerator JsonDownload()
{
string savePath =
Path.Combine(Caching.currentCacheForWriting.path,
"AssetBundleData.json");
using
(UnityWebRequest request = UnityWebRequest.Get(BaseURL))
{
// アセットバンドルの基盤データをダウンロードする
request.downloadHandler = new DownloadHandlerFile(savePath);
request.SendWebRequest();
if (request.isHttpError || request.isNetworkError)
{
//エラー
Debug.LogError(request.error);
yield break;
}
// アセットバンドルのダウンロードが完了するまで待つ
while (!request.isDone)
{
yield return null;
}
}
// jsonを読み込み
string[] JsonData =
File.ReadAllText(savePath).Split('\n');
for (int i = 0; i
< JsonData.Length; i++)
{
AssetBundleData.Add(JsonData[i].Split('/'));
}
}
// AssetBundleデータのダウンロード
IEnumerator CacheDownload(string Name, bool
Download)
{
//
アセットバンドルの追加データをダウンロードする
Hash128 Hash =
HashData(Name);
UnityWebRequest
Request = UnityWebRequestAssetBundle.GetAssetBundle(DataURL,
Hash, 0);
Request.SendWebRequest();
if
(Request.isHttpError || Request.isNetworkError)
{
//エラー
Debug.LogError(Request.error);
yield break;
}
//
アセットバンドルのダウンロードが完了するまで待つ
while
(!Request.isDone)
{
// キャッシュが存在しない
if (!File.Exists(GetNewPath(Name, Hash.ToString()) + "/__data"))
{
// キャッシュをダウンロード
if (Download)
{
// ダウンロード済みのサイズ/最大サイズ
Debug.Log("Download: " + Request.downloadedBytes + "/" +
Size(Name));
}
// サイズだけ取得する
else
{
// ファイルサイズ取得
Debug.Log("Size: " + Size(Name));
// ダウンロード処理を停止する
Request.Abort();
break;
}
}
yield return null;
}
if (Download)
{
// キャッシュの保存先のアドレスを保存
PlayerPrefs.SetString(Name, Hash.ToString());
}
}
// データのロード
public void Load()
{
//
キャッシュを1度も保存してない場合は処理をしない
if
(!Directory.Exists(GetPath(AssetBundleName)))
{
Debug.Log("キャッシュがありません");
}
else
{
// キャッシュをロード
AssetData = AssetBundle.LoadFromFile(GetPath(AssetBundleName) +
"/__data");
// キャッシュから画像を抽出
AllImage.AddRange(AssetData.LoadAllAssets<Sprite>());
// 画像を変更
image.sprite = AllImage[0];
}
}
// パス取得(保存済みのキャッシュ)
string GetPath(string Name)
{
return
Caching.currentCacheForWriting.path + "/" + Name + "/" +
PlayerPrefs.GetString(Name);
}
// パス取得(新しいキャッシュ)
string GetNewPath(string Name,string Hash)
{
return
Caching.currentCacheForWriting.path + "/" + Name + "/" + Hash;
}
// ハッシュ値取得
Hash128 HashData(string Name)
{
for (int i = 0; i
< AssetBundleData.Count; i++)
{
if (string.Equals(AssetBundleData[i][0], Name))
{
return Hash128.Parse(AssetBundleData[i][1]);
}
}
return
Hash128.Parse("");
}
// データサイズ取得
ulong Size(string Name)
{
for (int i = 0; i
< AssetBundleData.Count; i++)
{
if (string.Equals(AssetBundleData[i][0], Name))
{
return ulong.Parse(AssetBundleData[i][2]);
}
}
return 0;
}
}
3. CacheのInspectorから
BaseURL(AssetBundleDataをダウンロードするURL)
DataURL(asset_pack01をダウンロードするURL)
AssetBundleName(AssetBundleの名前 今回は"asset_pack01")
を入力します

※Dropboxを使用する場合 URLの最後の「?dl=0」を「?dl=1」にします
これで画像が変更すれば成功です
処理としてはAssetBundleDataをダウンロードし そこからasset_pack01のハッシュ値を取得して
その後asset_pack01のキャッシュがあるかどうかを確認し 同じのがあればキャッシュからロード 無かったり違かったりした場合はダウ
ンロードします
また オフラインならばキャッシュからロードします
今回は画像データをキャッシュ化しましたが テキストデータや音楽データもキャッシュ化する事ができます
キャッシュを削除したい場合は
Caching.ClearCache();
を実行します
※キャッシュを読み込む前に実行してください
ダウンロードしたいデータのサイズだけ取得する場合は
StartCoroutine(CacheDownload(AssetBundleName, false));
を実行します(後ろを「false」にする)
参考URL
Unity
のAssetBundleを試してみる - エンジニア的な事を何かしらアウトプットしておくブログ
【Unity】
UnityでAssetBundleをダウンロードする方法すべてまとめ - LIGHT11
【Unity】
AssetBundleのManifestファイルに書かれている内容について - テラシュールブログ
【Unity】
AssetBundleのハッシュ値を計算する方法 - LIGHT11
【Unity】
UnityWebRequest で ファイルを保存する方法 - うにてぃブログ
[Unity
2018.2] AssetBundleのキャッシュを完全に理解する - Qiita
UnityWebRequest
でダウンロードの進捗を取得する - Qiita
戻る