あらすじ
去年のアドベントカレンダーにて Unity でスクリーンセーバーを作る方法を模索してみたところ、Windows と Android で大まかな手順が見えてきました。
動かしてみると粗が目立つコードでしたが、あの後さらに整えたので、記録に残します。
更新情報
Windows
Windows 版を作る際は ExternalPrograms\Windows\UnityScreenSaverLauncher\UnityScreenSaverLauncher\Program.cs のレジストリ操作の行を適宜書き換える必要がありました。
まず、このレジストリキーをVC#プロジェクトの会社名と製品名から引用するよう変更しまして、 Unity でのビルド成功時に Unity プロジェクトの設定をVC#プロジェクトへ自動反映するスクリプトを書きました。
これでもう中のプログラムをいじる必要はありません!
しかし、いざ Windows 版をビルドして実際にスクリーンセーバーに設定してみたところ、なんと起動時にエラーが発生して実行できませんでした(不覚)
どうやら.exeの置いてあるフォルダーを基準にアセットファイルやら何やらを読むようなのですが、
本実行では手動実行時と異なり RUNDLL32.EXE がエントリーポイントになるため何も読めない事態に。
Unity 標準の.exeを置き換えるやり方では攻略できないので、 Unity 標準の.exeを子プロセスとして起動するよう変更しました。
インストール時の設定画面で即刻OKボタンを押しちゃうとウィンドウハンドルが無効になってクラッシュしちゃいますが、本実行できないよりはマシってことで。
Android
Android 版のスクリーンセーバーを閉じるときにエラーログが出てたのは、どうやら Unity のバグだった模様。
Unity を 2022.3.14f1 から 2022.3.18f1
に更新したら直りました。
(具体的には 2022.3.16f1 で直ったらしい→ リリースノート)
Android: Fixed PersistentUnitySurface potentially crashing on destroy if given context is not an Activity.
あと UnityPlayerDreamService のライフサイクルの実装を UnityPlayerActivity や BounceDreamService と見比べたら問題が見つかったので、修正したところキレイに起動終了するようになりました。やったね!
ところでシェーダーアート作るって言ってたのはどうなったのか
できました!
→ リポ
Qiitaのアバターに使ってた画像をベースにシェーダーを書いて Unity で動かしてみました。
RPGツクールVXでレンダリングしたときは500px四方で10秒くらいかかってたのに、GPUが本気を出せばフルHDさえも一瞬なのですね。やはりネイティブは強い。
せっかくなので動きをつけて、ついでにバッテリー状態に応じて色を変えるようにしてみました。
リリースビルドをリポに上げたのでよければ持ってってください。
→ https://github.com/TkoolerLufar/ShaderArtScreenSaver/releases/tag/v0.1.0
感想
アドベントカレンダーで詰めの甘かったところをしっかり追究できて、だいぶ満足しました。
シェーダーアートのコード書くとき Android 版で変な最適化が走ったり妙な困難があり、普段サーバーサイドでコード書くときは思いもよらない不具合が出て原因調査が大変だったのはいい経験です。
クライアントサイドって難しいですね。