ねののお庭。

かりかりもふもふ。

HoloLensのアプリ開発でIL2CPP使っていろいろハマった話。

お品書き<

  • インターン先で。
  • IL2CPPはつらいよ。(ハマったポイントとか)
  • 意外と知らない機能。
  • IL2CPP関係なくハマった点。

注意

この記事で書かれているものはUnity2017.4.8,visual studio2017,MRTK2017.4.1.0で起きた現象を元に書かれています。

インターン先で。

夏はインターンの季節です。自分はHoloLabに行っていたのですが、VRMのビューワーをせっせと作っていました。以下みたいな感じのですね。1万3千回も再生されてにっこにこです。

なのですが、HoloLensでVRMを表示しようとすると、Scripting BackendsをIL2CPPにしないとまともに ビルド出来ません なので今回のインターンではIL2CPPで頑張ってたのでその話を。

IL2CPPはつらいよ。

ビルド時間

まず死ぬほどビルド時間が長いです。解決方法は一応Unityがこんなことを言ってはいるのですが、インクリメントビルド以外は正直そんなに早くなった気がしません。インクリメントビルドも(C#の)スクリプトちょっといじっただけなのにC++のコードが大量にコンパイル走ったりするのでどっちにしろ時間がかかります。 一応settingみたいにDevelop buildとScripts Only Buildにすると、スクリプトだけ書き換えた場合にビルドが早くなるらしいのですが、初めてチェックを入れたタイミングでは差分以外もコンパイルが走ってオプションなしでビルドするより時間がかかるので、複数回スクリプトのみ変更を行う場合のみだけ使ったほうがよさそうです。 .NET(C#)だとUWPのプロジェクトに吐き出してもあとでC#スクリプトを直接書き換えればいいので1回のビルドで済むのですが、IL2CPPだと必ず2回ビルド噛ませないといけないので非常に時間がかかります。つらいですね。

windows difenderのディレクトリ単位の切り方

ここを

こうして

こうじゃ!

デバッグ

IL2CPPに吐き出した状態でデバッグするのはまぁほとんど無理と思ったほうがいいと思います。ビルドに死ぬほど時間持っていかれますし。なので可能な限りエディタでデバッグできるように頑張ります(これ意識すると大分学びが生まれる気がしています)(実機デバッグ至上主義をやめようと思った)。実機でデバッグするときは

Application.logMessageReceived

参考とか使うと大分幸せになれました。

プリプロセッサ

IL2CPPでは

#if UNITY_UWP

はfalse扱いになってそこはコードが走らなくなります。使うのは

#if WINDOWS_UWP

#if ENABLE_WINMD_SUPPORT

とかにしましょう。ハマりました。

I/O

Unityでは普通FileStreamでIOします(?)が、UWPではcapabilityを与えていても、FileStreamで外部のストレージを漁れません(素のUWPでも)。なので以下のような感じでOpenStreamForReadAsyncやOpenStreamForWriteAsyncを使わないとダメです。気を付けましょう。IL2CPPでFileStream使おうとしてもExceptionの細かいメッセージとか出てこないで、NULLって怒られるだけなので本当にわかりずらい。

using (var stream = await KnownFolders.Objects3D.OpenStreamForReadAsync(filename))
{
    var str = new byte[stream.Length];
    await stream.ReadAsync(str, 0, str.Length);
}

カメラ

同じコードでも.NETだと動くのですがIL2CPPにすると動きません。原因不明です。原因と解決策がまだわかってないのでそのうち調査します(分かった方いたら教えてくださいw)

ビルド

ビルドでIL2CPPのプロジェクトを吐き出したら、Package.appxmanifestのビジュアル資産->スプライトで画像を設定します。これをしないとビルドしても配置できません。C#の時みたいによしなにしてほしいものです。。。

パッケージ化

ビルドして配置して、アプリが正しく動作していることが分かっても、いざパッケージにしようと思うとこけます。こんな感じ でこけます。 これは.vcxprojを直接いじって、

<None Include="Assets\SplashScreen.scale-200.png">
     <DeploymentContent>true</DeploymentContent>
     <ExcludeFromResourceIndex>false</ExcludeFromResourceIndex> <!--デフォはtrue-->
</None>

などとしないとダメみたいです。

意外と知らない機能。

visual studioで#if falseの部分を書いているとき、シンタックスハイライトとかいろいろ効かなくて苦しいのですが、IL2CPPではプロジェクトに.Playerというのが吐き出されていて、そこではシンタックスハイライトやインテリセンスが効くので幸せになれます。

IL2CPP関係なくハマった点。

AppBarがめちゃくちゃ使いづらい。

OnTappedEventとかちゃんと設定できるようになってるくせに、発火されないというひどい仕様。 issue投げられてなかったら絶対気付かないやつ。

UWPで普通に使える名前空間でもUnityでは使えないものがある

普通のUWPでは使える名前空間とかがUnityでは#if WINDOWS_UWPとかで囲ってあげていても使えないものがあります(まぁそりゃそうですよね)。 ダウンロードしたファイル名とかの取得を最初ContentDispositionを使おうとしてたんですけど、普通のUWPでは使えてもUnityでは使えませんでした(プラグインとか挿せば使える?)。プラグインとか挿さないでもダウンロードしたときのファイル名はこんな感じで取れます。

var client = new HttpClient();
var responses = await client.GetAsync(new Uri(downloadUrl));
var fileName = responses.Content.Headers.ContentDisposition.FileName;

思うところ