HoloLensでAssetBundleDemoを動かす
皆さんお馴染みのAssetBundle。
AssetBundleはちゃんと使おうと思ったら色々と闇が深そうですが、とりあえずUnity Technologiesさんが公開しているAssetBundleDemoをHoloLensで動かしてみたいと思います。
なおAssetBundleDemoは以下にあります。
AssetBundleDemoの中でも、今回は「AssetBundleLoader」シーンを動かしてみたいと思います。AssetBundleLoaderシーンを動かすための手順は大きく以下の3つです。
- AssetBundleをビルドする
- AssetBundleServerを起動する
- デプロイ & 実行する
この手順自体はHoloLensであっても、他のプラットフォームであってもそう変わらないと思います。 ですが、UWP/HoloLens向けに多少ソースコードを修正しないと実行できないので、手順を追いながら適宜HoloLensで実行できるように変更していきたいと思います。
手順1:AssetBundleをビルドする
まずはAssetBundleとしてサーバーへ配置するファイル群を生成します。
ビルドターゲットをUWPへ変更する
Unityのメニューバーから[File]-[Build Settings]を選択すると、上記のダイアログが表示されます。 この画像の通り、Platformから「Windows Store」を選択し、「Switch Platform」ボタンを押下します。 UnityのロゴマークがWindows Storeのところに表示されたら、変更完了です。
AssetBundleビルドする
Unityのメニューバーから[Assets]-[AssetBundles]-[Build AssetBundles]を選択します。
これでUnityのプロジェクトディレクトリに「AssetBundles」ディレクトリが生成され、その中にアセットバンドルファイルが生成されて・・・いません。
どうやらビルドに失敗して、UnityのConsoleに以下のエラーが表示されてしまうようです。
ArgumentNullException: Argument cannot be null. Parameter name: path2 System.IO.Path.Combine (System.String path1, System.String path2) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/Path.cs:115) AssetBundles.BuildScript.CreateAssetBundleDirectory () (at Assets/AssetBundleManager/Editor/BuildScript.cs:19)
【修正1】UWP向けのプラットフォーム名を返すようにする
エラーメッセージを見ると、「Assets/AssetBundleManager/Editor/BuildScript.cs」の19行目、System.IO.Path.Combine()を呼び出しているところの引数path2がnullのようです。 ここをソースコードで確認すると以下のような感じになっています。
static public string CreateAssetBundleDirectory() { // Choose the output path according to the build target. string outputPath = Path.Combine(Utility.AssetBundlesOutputPath, Utility.GetPlatformName()); if (!Directory.Exists(outputPath)) Directory.CreateDirectory(outputPath); return outputPath; }
Path.Combine()の引数path2の部分は恐らく Utility.GetPlatformName()
の部分だと思われます。
このUtilityクラスは「Assets/AssetBundleManager/Utility.cs」にあるらしいので、そちらを見てみます。
public static string GetPlatformName() { #if UNITY_EDITOR return GetPlatformForAssetBundles(EditorUserBuildSettings.activeBuildTarget); #else return GetPlatformForAssetBundles(Application.platform); #endif }
このGetPlatformForAssetBundlesがnullになっているために、エラーが発生していそうです。 このメソッドはビルドターゲットやアプリケーションのプラットフォームに応じて、そのプラットフォームに対応する文字列を返してくれるっぽいです。
つまり先に答えを言ってしまうと、このメソッドの中では各プラットフォーム別にswitchで対応文字列を返しているのですが、UWP向けの条件がないためにnullが返ってきています。
と、いうワケで以下のコード中のコメントで // Add
と書いている部分を4行ほど追加してUWPへ対応させてみましょう。
private static string GetPlatformForAssetBundles(BuildTarget target) { switch (target) { case BuildTarget.Android: return "Android"; #if UNITY_TVOS case BuildTarget.tvOS: return "tvOS"; #endif case BuildTarget.iOS: return "iOS"; case BuildTarget.WebGL: return "WebGL"; case BuildTarget.WebPlayer: return "WebPlayer"; case BuildTarget.StandaloneWindows: case BuildTarget.StandaloneWindows64: case BuildTarget.WSAPlayer: // Add return "Windows"; case BuildTarget.StandaloneOSXIntel: case BuildTarget.StandaloneOSXIntel64: case BuildTarget.StandaloneOSXUniversal: return "OSX"; // Add more build targets for your own. // If you add more targets, don't forget to add the same platforms to GetPlatformForAssetBundles(RuntimePlatform) function. default: return null; } } #endif private static string GetPlatformForAssetBundles(RuntimePlatform platform) { switch (platform) { case RuntimePlatform.Android: return "Android"; case RuntimePlatform.IPhonePlayer: return "iOS"; #if UNITY_TVOS case RuntimePlatform.tvOS: return "tvOS"; #endif case RuntimePlatform.WebGLPlayer: return "WebGL"; case RuntimePlatform.OSXWebPlayer: case RuntimePlatform.WindowsWebPlayer: return "WebPlayer"; case RuntimePlatform.WindowsPlayer: case RuntimePlatform.WSAPlayerARM: // Add case RuntimePlatform.WSAPlayerX64: // Add case RuntimePlatform.WSAPlayerX86: // Add return "Windows"; case RuntimePlatform.OSXPlayer: return "OSX"; // Add more build targets for your own. // If you add more targets, don't forget to add the same platforms to GetPlatformForAssetBundles(RuntimePlatform) function. default: return null; } }
【修正2】GetStreamingAssetsPath()で適当なパスを返すようにする
上記を修正しても、今度は以下のようなエラーが表示されてAssetBundleのビルドに失敗します。
Assets\AssetBundleManager\AssetBundleManager.cs(162,56): error CS0117: 'Environment' does not contain a definition for 'CurrentDirectory'
問題となるコードはAssets/AssetBundleManager/AssetBundleManager.cs
のようです。
private static string GetStreamingAssetsPath() { if (Application.isEditor) return "file://" + System.Environment.CurrentDirectory.Replace("\\", "/"); // Use the build output folder directly. else if (Application.isWebPlayer) return System.IO.Path.GetDirectoryName(Application.absoluteURL).Replace("\\", "/") + "/StreamingAssets"; else if (Application.isMobilePlatform || Application.isConsolePlatform) return Application.streamingAssetsPath; else // For standalone player. return "file://" + Application.streamingAssetsPath; }
上記コードの中の
return "file://" + System.Environment.CurrentDirectory.Replace("\\", "/"); // Use the build output folder directly.
のところで、System.Environment.CurrentDirectory
が存在しない定義だと怒られているようです。
これはUnityがHoloLens用にビルドする際の.NetCore1.1ではSystem.Environment.CurrentDirectory
プロパティが存在しないためにエラーになっているようです。
.NetCoreのドキュメントを見ると、確かに.NetCore2.0からSystem.Environment.CurrentDirectory
プロパティが追加されたようなので、.NetCore1.1では存在しないようです。
しかしここのコード、実は何にしても影響ないので、先ほどのコードを適当なものへ変更します。
private static string GetStreamingAssetsPath() { if (Application.isEditor) return string.Empty; // ← 適当に変更 else if (Application.isWebPlayer) return System.IO.Path.GetDirectoryName(Application.absoluteURL).Replace("\\", "/") + "/StreamingAssets"; else if (Application.isMobilePlatform || Application.isConsolePlatform) return Application.streamingAssetsPath; else // For standalone player. return "file://" + Application.streamingAssetsPath; }
はい、適当にstring.Empty
にしちゃいました。
真面目にやるならSystem.Environment.CurrentDirectory
に代わる、.NetCore1.1で使用可能なカレントディレクトリを取得する方法を用いて設定してあげましょう。
改めてAssetBundleビルドを行う
上記修正が終わったら、改めてAssetBundleのビルドを行います。 再びUnityのメニューバーから[Assets]-[AssetBundles]-[Build AssetBundles]を選択します。
これでUnityのプロジェクトディレクトリに「AssetBundles」ディレクトリが生成され、その中にアセットバンドルファイルが生成されていると思います。
手順2:AssetBundleServerを起動する
Unityのメニューバーの[Assets]-[AssetBundles]-[Local AssetBundle Server]を選択します。
これで先ほどの「AssetBundles」ディレクトリの中身が公開されるようになります。
ServerとなるPCのIPアドレスを指定する
上記のLocal AssetBundle Serverを動かしているPCのIPアドレスを設定して、HoloLensからアクセス出来るようにします。
Assets/AssetBundleSample/Scripts/LoadAssets.cs
に指定します。
// Initialize the downloading URL. // eg. Development server / iOS ODR / web URL void InitializeSourceURL() { // If ODR is available and enabled, then use it and let Xcode handle download requests. #if ENABLE_IOS_ON_DEMAND_RESOURCES if (UnityEngine.iOS.OnDemandResources.enabled) { AssetBundleManager.SetSourceAssetBundleURL("odr://"); return; } #endif #if DEVELOPMENT_BUILD || UNITY_EDITOR // With this code, when in-editor or using a development builds: Always use the AssetBundle Server // (This is very dependent on the production workflow of the project. // Another approach would be to make this configurable in the standalone player.) AssetBundleManager.SetDevelopmentAssetBundleServer(); return; #else // Use the following code if AssetBundles are embedded in the project for example via StreamingAssets folder etc: AssetBundleManager.SetSourceAssetBundleURL(Application.dataPath + "/"); // Or customize the URL based on your deployment or configuration //AssetBundleManager.SetSourceAssetBundleURL("http://www.MyWebsite/MyAssetBundles"); return; #endif }
上記コードの19行目あたりから、以下のように変更します(抜粋)。
#else // Use the following code if AssetBundles are embedded in the project for example via StreamingAssets folder etc: //AssetBundleManager.SetSourceAssetBundleURL(Application.dataPath + "/"); // ←コメントアウト // Or customize the URL based on your deployment or configuration AssetBundleManager.SetSourceAssetBundleURL("http://(ServerPCのIPアドレス):7888/"); // ←コメントアウトを外してIPアドレスを指定 return; #endif
接続先は
http://(ServerPCのIPアドレス):7888/
となります。
UWPのインターネット受信許可を与える
UWPでは、セキュリティの関係でそのままではインターネットアクセスなどが行えません。これはAndroidやiOSなんかと一緒で、必要な機能の許可設定をしてあげる必要があります。 今回はAssetBundleServerとなるPCへの接続を行うため、「InternetClient」の許可を行います。
まずはUnityのメニュバーで[Edit]-[Project Settings]-[Player]を選択します。
選択するとInspectorパネルにPlayerSettingsが表示されるので、「Publishing Settings」を選択して「InternetClient」を選択してチェックを入れます。
手順3:デプロイ&実行する
これで一通りの準備が整いました。 HoloLensへデプロイして、実行してみましょう。
これでひとまずHoloLensでAssetBundleManagerを利用したAssetBundle機能を使うことが出来ました。