tl; dr(最近流行ってない気がするこの言い回し)
Unity 2019.2 で Android の CallStatic やって親クラスの static メソッドを呼ぶと死ぬ → Unity Mobile Notifications 使うとこれが原因で死ぬ → 公式も直すつもりがないので Unity 2019.2 は使ってはいけない
発端
2019.2.8f1
では問題がない、少なくとも 2019.2.14f1
2019.2.15f1
で問題が起きる。
原因
子クラスのクラスオブジェクト、あるいはクラスインスタンスオブジェクトで親(基底)クラスの static メソッドを呼ぶと、子クラスにその static メソッドが生えてない場合、親に向かって探しに行かずに死ぬようになった。
そもそもおすすめの解法
static メソッドを呼ぶ場合、それを定義してるクラスを対象に呼ぶべきで、派生クラスから呼ばないべき。
余談(やっぱり Interface 大事)
特に派生クラスを返しうる実装においては、基底クラスを返すのではなく、それに必要な interface を定義して、それを返す方が設計として正しいのではないかと思う。
自分の記憶では interface は static であってもメソッド生やせなかったと思うし……生やせたとしても、その interface クラス名で呼ばないとコンパイルエラーになったと思うし……。
一方その頃 Unity Mobile Notifications では
こいつの Android 実装において UnityNotificationManagerOreo
クラスは UnityNotificationManagerNougat
クラスを派生して UnityNotificationManagerNougat
クラスは UnityNotificationManager
クラスを派生している。
これは Oreo, Nougat, さらにそれより前の Android において、それぞれローカル通知の実装が異なり、それを吸収するためのクラス構造となっている。OOPだ。
これは UnityNotificationManager.getNotificationManagerImpl
を呼ぶと、その Android SDK バージョンにおいて3種類の中から適切なクラスインスタンスを返してくれる作りで利用されている。
そしてふたりが出会う
ここで UnityNotificationManager
に定義されている static メソッドは UnityNotificationManager
クラスオブジェクトから CallStatic してくれればいいのだけど Unity の実装では UnityNotificationManager.getNotificationManagerImpl
で返されたクラスインスタンスオブジェクトから CallStatic がされる。よってこれによって子クラスが返されると死ぬ。
Fixed in 2019.2.22f1(直ったとは言ってない)
2019.2.22f1 で直る予定らしい
Fixed in 2019.2.22f1
とある。それじゃバージョンアップすっかー……
Unity 2019.2.19: 22 Jan, 2020
Unity 2019.2.20: 4 Feb, 2020
Unity 2019.2.21: 10 Feb, 2020
Unity 2019.2.22 は少なくとも約3ヶ月間リリースされていない。 つまり見捨てる訳ね。
あるいは 2019.2.8f1
まで戻ればいいんだけど (何のためのバージョンアップなんだろう……)
SpriteAtlas を使っている場合、戻ることもできない地獄が待っている。
SpriteAtlas は 2019.2.19f1 まで使い物にならない
SpriteAtlas がリビルドされるたびに .meta の中身が書き換わるのでソース管理すると無駄にバージョンが上がっていく不具合がある。 2019.2.19f1
で直った。
- https://unity3d.com/jp/unity/whats-new/2019.2.19
- https://issuetracker.unity3d.com/issues/sprite-atlases-are-modified-after-building
- https://forum.unity.com/threads/spriteatlases-keep-changing-their-hash-without-sprites-changing-polluting-source-control.754739/
つまり SpriteAtlasを誤魔化し誤魔化し使っていく事でAndroidの不具合を回避する もしくは Unity Mobile Notifications を使わない あるいは Unity 2019.2 を諦める から選ぶことになる。
個人的におすすめするベストプラクティス
できる限り Unity Technologies によるネイティブ実装を求めないようにしていく。自前で作るのが多分一番いい。Unity Technologies というのは Unity Ads やら、あるいは儲かってる会社からお金を取るビジネスモデルなので、お金に関わるところの実装であればおそらくテストやサポートが厚そうだという期待は持てるが、通知だとかそのほか変化の激しいモバイル側の実装までは品質を維持する期待が持てないので、そのあたりは全部自己責任でやるのが有事の際に対応しやすいと考えられる。