2022年11月21日月曜日

【Unreal Engine 5.1 on macOS 】UE5.0と比べて影が濃くなった現象と回避方法 Lumen on macOS

【環境】
MacBook Pro (2021年モデル M1 Pro, 14-inch, 16GB Memory) macOS Ventura 13.1
Unreal Engine 5.1.0 正式版(Preview版では無いの意味)
※2023.2.8 Unreal Engine 5.1.1 でも試してみました。末尾参照。
※2023.3.23 また、Unreal Engine 5.2.0 Preview 1 にて本事象が解消されました!
※2023.5.12 Unreal Engine 5.2.0 正式版リリースされ、問題ありませんでした!

【症状】
Unreal Engine 5.1.0がリリースされたので使ってみた。
Unreal Engine 5.0.xと比べて全体的に動作も爽快になって素晴らしい!と思っていたが、そういえばなんとなく影が暗くなった気がする。

よってThirdPersonプロジェクトで比較してみた。

まずUE5.0.3の場合:


次にUE5.1.0の場合:


UE5.0.3では右端の壁の影の格子線がうっすらと見えるが、UE5.1.0では真っ黒である。

壁に寄って、マネキンも置いてみる。

【UE5.0.3】

【UE5.1.0】


UE5.1.0では影が完全に漆黒である。


【回避策】
根本解決では無いと思うが、PostProcessVolumeのパラメータを変えることで、真っ黒現象は回避可能だった。

設定対象:レベル上の Lighting → PostProcessVolume
設定内容:Global Illumination → Lumen Global Illumination → Final Gather Quality をデフォルトの 1.0 から最小値(0.25)にする。



【UE5.1.0 対応後】
UE5.0.3の見た目とほぼ同じになった。

なお、以下の値を境界にして、真っ黒↔︎見えるが切り替わる。(これがいわゆる「マジックナンバー」? Unreal Engineとしては初めて見つけました✌️)
・0.472657以上:影が真っ暗
・0.472656以下:影が真っ暗ではなくなる

また、不思議なことにマネキンの関節部分だけが、真っ黒から白に変わるのである。
メッシュ内部の何か(Material)の要因も関係しているということだろうか?


なお、エディタ上では漆黒問題は回避できたが、シーケンサーの Movie Scene Capture (Legacy) や Movie Render Queueで動画出力した場合には、やはり残念ながら影が真っ黒になってしまう。。
シーケンサーで使用するカメラ側のFinal Gather Qualityを0.472656以下にしてもダメだった。


【考察】
Unreal EngineをUE5.1.0から使い始める人は、この影が真っ暗なThirdPersonプロジェクトとかから触る訳で、「なんじゃこれは?Unreal Engineってすごいと聞いてたけどこんなに見づらいの?」とか思われないか、Epic Games社が心配である^^
(むしろ問題のなかったUE5.0から使い始めた私がラッキーだったのか???)

今回触った設定値にもLumenとある通り、Lumenバージョンアップ周りの影響か、またはMacならではの現象なのだろうか?

リリースノートも以下の通りである。(新機能紹介のトップバッターですね。)
Lumen、Nanite、および仮想シャドウ マップの更新

次世代コンソールや次世代対応 PC で 60 fps で動作するゲームや体験に対応するための 
Lumen ダイナミック グローバル イルミネーションおよび反射システム、Nanite 仮想化
マイクロポリゴン ジオメトリ システム、仮想シャドウ マップ (VSM) の基盤を確立することで、
高速の対戦ゲームや詳細度の高いシミュレーションをレイテンシーなく動作させることができるように
なりました。

私は初心者すぎて、一体どの技術が影響しているのか見当もつかないのだが、以下のようなフォーラムでも議論されている通り、最近でもやはりMac上でLumenが動くだの動かないだのの話は続いているようである。
※トピックはいくつもあるのだが、Epicからの公式返答がどこを見ても見当たらない^^この件については明言を避けることに内部的になっているのだろうか?^^
→上記1つ目のフォーラムにて、Epicスタッフの方から返答がありましたね!末尾参照。

※なお、タイトルに「Lumen on MacOS」と記載したのはDeveloper Forumを眺めていると同じようなトピックが多かったから。原因の可能性であるかも知れないが、明確に原因という意味で書いたわけではない。
ただし、公式ページにもLumenグローバルイルミネーション部分に、実は同じような比較画像付きで説明があった。
比較画像でもLumen GIがOFFの場合は、影部分が漆黒になっていることがわかる。

また、Lumen Global Illuminationの「Final Gather Quality」とは、Lumen のグローバル イルミネーションの品質を向上させ、レンダリングされるノイズを低減する値っぽい。色々サンプルを見ると、値が大きいほどノイズ除去効果があるようだ。
今回の事象は、値を上げて品質を上げたつもりが、むしろ影が漆黒になってしまう、といった感じだろうか。
精度をあげることで反射とかを計算しすぎて、ある臨界点を超えて明るさよりも影の力がまさってしまっているのだろうか?
UE5.0 で問題なかった頃は、影部分もうっすら見えていたので、明るさ>暗さ だったが、UE5.1 でFinal Gather Qualityの値を上げて品質向上させると、なぜか 明るさ<暗さ になっているとも言える。しかしいくら品質を良くしようが悪くしようが、明るさ>暗さ の不等式が逆転することはありえないはず。。
上記は単なる直感的な説明になり、また、繰り返しになるが、MacOS環境上でもUE5.0では問題なかったので、MacOS環境上でUEを動作させた場合のLumenがらみの何かの「噛み合わせ」の問題と思いたい。

※そもそもWindowsでは問題ないか気になるところです。(試して比較できればいいのですが。。)
※キーワードだけでも、Lumen, PostProcess, Global Illumination (GI), 仮想シャドウマップ(VSM)とかがあって、さらにプラットフォームとしてのMacOSが絡んでくる訳ですね^^
MacOSもちょうどMontereyからVenturaへのバージョンがあったりと。。(VenturaではゲームAPIのMetal 3が話題でしたね。BioHazard Villageが移植されたりしました!ただしMetal 3が今回の問題と関係あるかどうかは私の知識では不明です。そもそもUEのMetalに対する取り組みとかロードマップとかも私はまだ知識が追いついておりません。。(あくまでもiOS用にビルドするためだけに使う、という姿勢?))

私としては、早く改善版が出てくれるか、解決策がフォーラムで議論されるかを待つばかりである。(UE5.0.xでは問題なかった訳であるし、個人的にはUnreal Engineのデフォルトパラメータが噛み合ってない系の話であって欲しい。。)

※なお、私が知らない間にエンジン全体に関する設定を変えてしまっていて、そのせいではいけないと思ったため、UE5.0.3及びUE5.1.0はアンインストールした上で再インストールして試してます。(1日がかりの作業だった。とは言っても約16GB×2つのダウンロードを待つだけでしたが。。)

※ちょっとだけUEについて知見を得たので書いておくと、やはりNaniteとLumenとかPostProcess, GI, VSM, ... は密接に関わってるようで、やはりMac+Naniteの問題の影響なのだろうか?
こちらにも書いたが、MacではNatiteは対応されていないし対応予定もないので、Macは置いてけぼりにされるのだろうか。。。?😢
それとも下記はあくまでも、「Mac上のグラフィックス API (Metal) にはUnreal Engineのエンジンの根本的なところから対応することはないけど、動く範囲では動かせる」と言った意味合いなのだろうか?
UE5で(もしかするともっと前から?)ノンゲーム(映像制作とかアニメとか)分野でも「最終アウトプットに近い状態で制作が進められるので、制作フローが根本的に変わる」とかあったと思い、映像分野(アート分野)に強いMacに対するUEの対応方向は気になるところである。
There is no Mac OS support for Nanite, nor is any likely in the future due to 
graphics API limitations.

(Google翻訳) Nanite に対する Mac OS のサポートはありません。また、グラフィックス API の制限により、
今後もサポートされる可能性はありません。

NANITE FOR EDUCATORS AND STUDENTS より抜粋


(余談)実はもう一つの問題があって、Megascanから追加したメッシュが何故かある日突然、表面の見た目が真っ白になってしまった現象があり、現在未解決である。
一応、一時的な回避策としては、画面右上のSettings → Preview Rendering Level をAndroid Vulkanとかにすれば、モバイル上の見た目を再現してくれて表面画像も描画されるのだが、根本解決ではない。
ちょっと余談で書くにはボリュームが大きくなってしまうので、こちらも解決したら別記事を書く予定です!

→こちらの問題もUE5.2.0にて解消されておりました!
 (こういったエンジン側の問題(?)となると、もう原因は追えませんね。。)

ーーー
2023.2.8 追記
Unreal Engine 5.1.1 がリリースされました!
早速、新規ThirdPersonプロジェクトを作成して確認してみましたが、残念ながら影漆黒問題はそのままでした。。。

でも、Point LightとRect Lightは効くようになったんですね。
UE-157521	Point and Rect Lights on Mac do not cast or project any light
最初に書きましたが、またそもそも話になりますが、もしかして「現実に近づけた結果UE5.1.xの影描画になったので、UE5.1.xの方が正しい。UE5.0.xの方が現実とずれていた。UE5.1.xからは使う人が自分で少なくとも何らかのライティング(Lighting)設定することが前提!」ということなのでしょうか?(Windows版と比較できないことが痛い。。)

Point and Rect Lights on Mac ということで、Mac上の問題として認識されている訳で、それであれば、Point LightとかRect Lightとかの話以前に、影漆黒問題も認識されてると思うのだが、何せ公式見解(回答)がないので推測するしかない状況なのである。。

ーーー
ちなみに、UE5.1.1 でPoint LightとRect Lightは効くようになった訳だが、UE5.1.0で漆黒問題の調査時にPoint Light・Rect Lightも試してたが、どうりで効果がなかった訳だ^^
Point LightとRect Lightの問題だけ取り上げても「一体何が正解か?」がわからなくなってしまった感がある。(改めて、UEを期待を持って使おうとしてるユーザさんに対してEpicさん大丈夫だろうか?^^)
Point LightとRect Lightとか、結構基本的な機能な訳で、テスト・動作確認もしてたのかな?的な話になり、一体UE5.1.xからはベータ版リリースになったのだろうか?とユーザに思われないか、とても心配である。。

ーーー
こちらに別の回避策が投稿されてました。
Lumenは諦めて、Global Illumination (GI) Method をScreen Space (Beta) にする、という回避策ですね。
これであればシーケンサーからの動画出力も漆黒問題はありませんので、シーケンサーで動画作成されてる方は、根本解決されるまではこちらの回避策の方が現実的かも知れません。
ただし、「絵作り」(Postprocessとか)を実施済みの場合は、GIをLumenからScreen Spaceにすると見た目に結構な影響があるため、もう一度絵作りのやり直しは必要になってきそうですが。。

さらに、こちらにスタッフの方から内部的な回答もありましたね!!!
恐縮ながらGoogle翻訳させて頂きます。
M1 および M2 アーキテクチャは現在、HW で 64 ビット アトミックをサポートしていないため、
現時点では Nanite と Lumen with RayTracing を実装できません。
レイ トレーシングなしのルーメンは動作するはずですが、特定の問題が発生している場合は、
バグ レポート システムからお知らせください。

今後の M3 アーキテクチャがこれをサポートすることを期待していますが、これらの機能をさらに
実装する方法をコミットする前に、まだ様子を見るのを待っています.

どうやらM1/M2チップでは、「64 bit atomics」をサポートしていないため、Nanite と Lumen with RayTracingが対応されてないようです。
何かしらやりようはあるのかも知れませんが、少なくともM3チップのアーキテクチャが判明してからとなりそうです。
(結果としてM3チップで上記機能サポートされ一件落着するのか、またはM3チップ上で機能サポートされず、UEも未サポートが続くのか、はたまた、UE側が「しょうがないか」とか言って次善策で対応してくれるのかは、蓋を開けてみないと分からない。。)

とりあえず、MacOS上ではしかるべき理由があってNanite & Lumen (の全機能まで)はサポートされていないということが分かってよかったです。
また、着地点がお互いにベストな結果になることを期待したいと思います!

ーーー
ソフトウェア開発をされた方であれば分かると思うが、今回の件で言うと、UE5.0.xからUE5.1.xへのバージョンアップによって漆黒問題が発生した訳だが、バグだからといって簡単に「引っ込める(バージョンを戻す)」ことができる箇所と、そうでない箇所がある。

UE5.0.xからUE5.1.xに切り替えて、エディタ全体の動作が爽快になって驚かれた方もたくさんいるかと思うが、それはやはり全体にわたる修正とか、アーキテクチャに関わる修正な訳であって、「漆黒問題が発生したから、ここだけバージョン戻せ」とはいかない訳である。
(もしも戻したら、そこのソースコードはUE5.0.x→UE5.1.xで作業した分がまるまる無駄になるということ。)
無駄にならない・させないために、次期バージョンアップで実現したいこと(ビジョン)から入って、細かい設計まで慎重に行う訳である。
(もしもそこがミスっていては、確かに残念な結果になってしまうのであるが、ここまでユーザの支持を得ながら成長されてきて、場を重ねてきた猛者の方々が方針を打ち出しているはずなので、流石にそこまで大きな過ちはないと思う。)

よって漆黒問題はいわば二次的・副次的な結果生じた問題であって、解決するには現状路線を進んで行って解決するか、または大幅に方針転換して(それこそこの問題のためだけに)対応するか、のどちらかになるのだが、上記の通り後者はまずあり得ないだろう。

いちUEユーザとしては、MacOS + UE 環境がお互いにベストな着地点に到達してもらうことを願うばかりである。

ただ、本記事の記載動機でもあるが、MacOS + UE5.0.xから使い始めて漆黒問題もなかったことを知ってるだけに、UE5.1.xの間はLumenを諦めなければならないのがなかなか決心が付かない、と言いたいだけであった。

まあ今回スタッフの方からも原因の説明があった訳で、また私個人的にはMacOS + UEで映像制作をメインに使っているため、解決されるまではGI MethodをScreen Spaceにすることで対応しようと思う。
※あ、あとM3チップ + UEで解決されたとしても、M1/M2 Macはどうなるか次第ですね^^M1/M2 Macもどこをどう通るか分かりませんが、うまいこと対応されるといいですね!または、このためだけに買い替えるか!?(というか、このためだけに買い替える余裕があるのであれば、MacBookは10,20,30,...万はするのでWindows + RTX30xxとかにした方が良さそう?^^これもUEとかゲーム分野に目覚めて本格的にやりたければですが。←Macで3D映像制作したい人マイナス1人^^こう言うところの「シェア」的な点でもMacはまだ弱いですかね?(こう言う意味まで含めてMac側もWin-Winの関係を作れるかですね!) まぁホットな話題といえばホットな話題でした。。)

ーーー
2023.3.23 Unreal Engine 5.2.0 Preview 1 が利用可能になりました!
早速ThirdPersonプロジェクトで試したところ、漆黒問題も直っておりました!!!🎉

シーケンサーの Movie Scene Capture (Legacy) や Movie Render Queueで動画出力しても問題ありませんでした。
対応ありがとうございました!
(Macで3D映像制作したい人がマイナス1人しなくて済みました😅)

ーーー
2023.5.12 Unreal Engine 5.2.0 正式版がリリースされ、漆黒問題も問題ありませんでした!
Movie Scene Capture (Legacy)、 Movie Render Queueも大丈夫でした。

リリースノートのBug Fixedや改善項目中には、本トピックの影漆黒問題に対する直接的なものは見つけられませんでしたが、リリースノート中に以下が挙げられており、この辺の話だったのでしょうか?
Hardware ray-tracing support for Lumen is not supported on macOS, 
which means Lumen will fall back to using a software-only ray-tracer. 
This means Lumen will produce lower-quality results (for example, 
reflections are less detailed and dynamic meshes are not visible in them) 
on Apple Silicon compared with devices that have hardware ray tracing support.
Unreal Engine 5.2 Release Notes | Unreal Engine 5.2 Documentation より抜粋

ハードウェア・レイトレーシングからソフトウェア・レイトレーシングに「戻す」(fall back) するとありますね。

UE5.1.x での回避策として、Final Gather Quality ≦ 0.472656 を境に、漆黒⇔そうでないが、綺麗にOFF/ON状態になっており、これがH/W Ray-TracingかS/W Ray-Tracingの境界線だったのでしょうか?
Final Gather Quality ≧ 0.472657 ではクオリティを上げるためにH/W Ray-Tracing処理になるが、Apple Silicon MacのGPUとの相性?とかの問題で、うまく処理されずに、結果的に影部分が漆黒状態になっていたとか?

そしてこの問題点はすぐには解決できないとかで、UE5.2.0 では(諦めて)全てS/W Ray-Tracingに「戻した」(fall back)ということだろうか?

ということで、本事象はどうやら UE5.1.x だけ特有の問題だったっぽい。
直ってくれれば問題ないわけで、この点について対応していただいて本当に助かりました!

ちなみに最後に、この内容はEpic Games DEV COMMUNITYフォーラムにも投稿させていただきました。

2022年10月16日日曜日

【Unreal Engine 5.0 on macOS 】シーケンサーで、FKControlRigのAdditiveにするとMesh(Actor)が消えて編集できない

シーケンサー(Level Sequence)で、アニメーションを作る時に、
SkeletalMeshのFKControlRigでアニメーションを作りたい場合がある。
Unreal Engineのリファレンスには、既存アニメーションをベースにして、
FKControlRigの動きを追加できる機能として、FKControlRigを「Additive」にするやり方が
載っている(※1)のだが、macOSだからなのか分からないが、うまくいかなかった。
実際の作業手順的には以下のようになる。
・シーケンサー(Level Sequence)を開く
・SkeletalMeshをシーケンサーに追加
・追加したSkeletalMesh(Actor)でベースになるアニメーションを設定
・追加したSkeletalMesh(Actor)に対して、FKControlRigを追加
 →SkeletalMesh(Actor)はFKControlRigに従って、デフォルトポーズ(Aポーズ)になる。
・FKControlRigを右クリック→Additiveを選択(ONにする)
 →SkeletalMesh(Actor)が消える。
  見えないだけかな?と思い、シーケンスの再生や動画出力してみてもやはり見えないままだった。


【環境】
MacBook Pro M1 (2021年モデル) macOS Monterey 12.6 / Ventura 13.0 Beta
Unreal Engine 5.0.3

【解決策1】
この前発表された、まだ正式版ではないが、Unreal Engine 5.1.0 Preview版では、本事象が直っていた!!!
macOS+Unreal Engineでゲーム制作よりも映像制作がメインの方は、このAdditiveが使えるか使えないかは結構クリティカルな問題だと思うので、とりあえずUE 5.1.0 Preview版を使うのもアリかと思う。

※P.S. 2022.11.16 Unreal Engine 5.1.0 が正式版になりました! Additiveも正常動作しております。これでMac環境 + Additive 問題も一件落着ですね。よかったよかった✌️
(細かい点ではシーケンサーからの動画出力を「Movie Scene Capture(Legacy)」にするとAdditiveが効いてくれない。「Movie Render Queue」にすれば問題ない。(これは本当に焦った^^映像制作時に、途中経過版はとりあえず「Movie Scene Capture(Legacy)」で確認して、最終出力時に「Movie Render Queue」を使うというやり方をしている人もいるかと思うので要注意))

全体的にも動作が爽快になっている感じがします。素晴らしい!
あ、でも色味の問題が新たに発生。。詳細はこちら「UE5.0と比べて影が濃くなった」を参照。

※なお、 Unreal Engine 5.1.0 Preview 1 だと、SkeletalMeshやPhysicsAssetを配置するとメッシュ表面に影がチラついて以下のメッセージが表示された。
your scene contains a skydome mesh with a sky material 
but it does not cover that part of the screen
また、ゲームをRunしてみて停止後に以下の警告が出ていた。
StaticMeshComponent0 has to be 'Movable' if you'd like to AddImpulseAtLocation.
ちょっと調べたら、SkeletalMeshやPhysicsAsset配下のStaticMeshのMobilityをMovableにすれば良さそうだが、StaticMeshのDetailsには該当プロパティは表示されていないので、どうすればいいのだろう?と思った。

しばらくしたら、Unreal Engine 5.1.0 Preview 2 が出ていて、そちらで試したら上記現象は解消されていました👍(深追いしなくてよかった😅 公式もアナウンスしてますがPreview版なので本格プロジェクト用で使おうとせず、このあたりは一歩引いて接しましょう。。最初に書いた「とりあえずUE 5.1.0 Preview版を使うのもアリかと思う」ということと矛盾しますが。。)

ーーー
ついでに書いておくと、macOSでUnreal Engine 5.0.x を使ってると、起動時に以下の警告が毎回出ていて鬱陶しかったが、これも Unreal Engine 5.1.0 で直っていた!
5.0.xのエラー1個目は、内容通りシステム設定のFirewall設定の許可項目にUnrealEditor.appアプリケーションを追加したがダメだった。
Do you want the application "UnrealEditor.app" to accept incoming network connections?
2個目のエラーは、Unreal Engine内部のメッセージなので深く調査はしていない。
UE 5.1.0 で解消されたので、もうこれ以上は深追いしないし、しなくて済む!!
'MegascansPlugin' is Incompatible








【解決策2】
解決策というか、別のやり方。
Unreal Engine 5.0.xの場合は、Additiveを諦めてベースとなるアニメーションをControlRigにして、生成されたControlRigをいじくって自分のやりたかったアニメーションに編集するやり方。
・ベースになるアニメーションを追加
※もちろんアニメーションの組み合わせ(Weightによる自然なアニメの切り替わりや、アニメの重ね合わせなど)で済むのであればそれに越したことはない。つまりベースのアニメは組み合わせでほとんど作っておく。
・ベースのアニメができたら、シーケンサーのSkeletalMesh(Actor)を右クリック ※バックアップは取っておきましょう(以下同様)
→Edit With FK Control Rigを選択。ダイアログが表示されるのでCreateを選択
→ベースとなったAnimationの方はグレーアウトされ、FKControlRigに全コマのキーが生成される。
→FKContorlRigを頑張っていじくって、ご自身のやりたかったアニメーションに加工していく。

解決策2の問題点としては、Edit With FK Control Rig後に「やはりここに別のアニメーションを追加したい」とか「出来上がったものに、続きのアニメーションを追加したい」といった時がめんどくさい。
一応その手順は、
・シーケンサーのSkeletalMesh(Actor)を右クリック
→Bake Animation Sequence。ダイアログが表示されるので名前をつけて保存する。
→シーケンサーのSkeletalMesh(Actor)のFKControlRigを削除。
 Animationに前ステップで保存したAnimation Sequenceを選択。
となるかと思う。

補足として、そもそもアニメーション業界やゲーム業界の実態は私は知らないので、ここに書いた内容はそれら「主流」のやり方とはマッチしていないかもしれない点、ご注意いただければと思います^^
(ゲーム業界といっても、各種シーンのアニメーションばかり作っておられる部署もあったりする?デザイナやモデリングを専属としている方も「いるんだろうな」くらいの知識です^^;)
(プラットフォーム的にもやはり主流はWindows?そしてWindows版であればUnreal Engine 5.0.xでもAdditiveは正常機能してる?一応GoogleとかEpic Games DEV Communityも英語文献含めてmacOS + Sequence + FKControlRig + Additiveとかで検索したが、それらしいトピックは見つからなかった。(UE5が出始めだったから?UE5.1.xで直ったので「まぁいいか」くらいの感覚))

こちらにも書いたが、MacではNaniteはサポートされていないし、される予定もないらしい。
業界的にはMacはデザインとかビデオ編集とかアニメーションに強みがあると思っていたが、「ゲームデザイン」「ゲームアニメーション」とかゲームがらみでUnreal Engineが本格的に使われてはいないのだろうか?分業で、Naniteに関係する箇所以外だけやってるとか?
Naniteはあくまでリアルタイム編集がやりやすくなるだけだから、アニメーション現場とかでNaniteが使えないMacでも問題ないということ?
人によってはWindowsとMacを行ったり来たりしながら作ってるとか?


2022年8月2日火曜日

重複排除記憶装置および動画骨組み形成圧縮機構

圧縮方法の基本的な考えとして、テキストファイルであればアルファベットの出現率が高い方から短い符号を割り当てて行って辞書化(キー・バリュー)して圧縮する方法がある。
これは1文字(1バイト)ずつ見て行く方式であるが、英語であれば英語の、日本語であれば日本語での文字のつながりの特徴・パターンがある訳で、そこまで考慮すればより効率の良い圧縮ができるであろうことは自明である。(というか実装されてるはず。)
(1ファイル中で全部英語とか、全部日本語とかであれば良さそうだが、複数言語が入り乱れているとオーバーヘッドが発生しそうである。また文法とか単語がルールに則っている間は良いが、突然(敢えて)変な言い方をしたり、敢えてスペルミスをした文章を載せる場合は、そこだけ「生(raw)情報 」としてエスケープしたりと、こちらもオーバーヘッドがかなり発生しそう。と言うことで実装はかなり大変そうである。)


今回のアイデアとしてはまず、テキストファイルであってもバイナリデータとみなして、パターンをとらえて圧縮するようにする。
そして、それを記憶装置全体に適用する、と言う物である。

解消されるポイントとしては、
・ファイル種別によってヘッダとか「決まりきった」書き方の箇所とかの重複した無駄な容量を節約できる。
・人によって同じようなファイルが集まる傾向がある(はず)なので、重複した無駄な容量を節約できる。(その人の作業で発生するバックアップファイルとかは少なくとも存在するだろう)
・つまり記憶装置全体としては使用者の特性にあった圧縮ができる。
といったところ。(話を分かりやすく単純化しているが、実際はどこまでも応用可能である。)

そういった情報を集めていけば、「現時点における、この組織の特性」が抽出できるので、以降はそのパラメータ決め打ちで圧縮していけば良い。
あわよくばクラウド全体・全世界に拡張できる。

問題点としては、
・パターン抽出の「枠の大きさ」はどれくらいが適切か。また「入れ子」も許容するのか。
・この方式はある時点の記憶装置全体の状態を基にパターン抽出する発想のため、変化に弱い。つまり書き込みがある場合には向いていない。
といったところか。

まず「枠の大きさ」「入れ子」についてだが、簡単に言うと最小公倍数で括り出した方が良いのか、最大公約数で括り出した方が良いのか、と言うこと。
最小公倍数で括ると言うのは、最初に書いた例だと英字であればアルファベットのeが一番出現率が高いので一番小さいサイズの符号に置き換えて、次は…と言った感じである。
そして入れ子というのは、一回符号化して出来上がったデータを再度パターン抽出して、今度は例えば2バイトの枠に広げて同じパターンを発生頻度の高い順に小さいサイズの符号に置き換えていく、ということ。
1回目の符号化であれば、符号化したものが1バイトを超えてしまっては圧縮にならない。
2回目の符号化であれば、符号化したものが2バイトを超えてしまっては圧縮にならない。
また、符号化したものが1回目のものなのか2回目のものなのか識別できる必要がある。
これを3回、4回と入れ子にしていけば圧縮率は高くなるかもしれないが、その分読み出す時の復号化の処理に負荷がかかることになる。
(1マシンで考えると大いなる無駄だろうが、クラウドで考えれば「復号化サーバ」がいて、全ての符号化辞書情報をメモリ上のキャッシュとして確保できるのであれば、このサーバにサーバに復号化だけ任せれば良いが、でもやはり処理要求が多すぎてI/Oは追いつかなそう。)

ということで、枠が小さすぎると細かくなりすぎて復号化が大変になるし、枠が大きいと復号化は簡単だけどあまり圧縮の意味がないため、どの程度の枠が圧縮率・読み出し速度のバランスとして最適なのかは実際のデータを基に計測する必要がある。

−−−−−−−−−−
アイデアの発端としては、もう編集されることがない決定文書とかアーカイブファイルとか動画とか、I/Oで言うと「読み取り」しかされないファイルは最大限容量を節約して良いのでは?と思った点。現在のストレージ技術では、全く同じファイルとかかなり似通ったファイルでも律儀にディスクスペースを使うしかないため、そこのブレークスルーになれば良いかと思った。

また、現在のクラウドストレージサービスでは「容量無制限」サービスは存在しないが、それは、そんなことをすれば絶対に誰かがディスクを「食い尽くす」人が出てくるだろうし、そう言う人を防ぎようがないからであろう。
しかし、このアイデアが実現すれば、そういった輩がどれだけ同じ巨大ファイルをストレージに書き込もうとしようが、それは全て同じ「符号」になるだけなので、「あぁ意味ないな」と悟ればそんな無意味なことをする人もいなくなるだろう。
そして「容量無制限」サービスも出てくるであろう。
※このアイデアを本気で実現すれば、もしかすると「ファイル容量」と言う考え方も根本的に変わってきそうである。

更にいっておくと、先ほどのストレージを食い尽くそうとする人の例では、同じ巨大ファイルで無駄にネットワークの帯域を使う必要もないことに気づくだろう。最初にハッシュ値などを確認してサーバから「アーカイブ済みですよ」応答があれば、クライアントは何も送らな行くて良い。
といったようにネットワークにもとても優しくなる。
(一部だけ符号化済みの場合は「xバイト目〜xバイト目まで送ってね」と返す、などなど。とは言っても「ファイル全体のハッシュ値」では差分は分からないため、この辺は要検討)

−−−−−−−−−−
なお、記憶装置(ストレージ)についてのアイデアであるが、アクセス権限やセキュリティについては、更に細かい検討が必要である。(アクセス権をちょっと考えると、符号化した方の情報にも、情報の元となったファイル&アクセス権の辞書が必要になりそう?)
このアイデアの特性が「書き込みに向いてない(リアルタイムの変更に弱い)」と言うことから、コンシュマー向けにはあまりならなそうである。
しかしビッグデータを抱える企業としては、ストレージの大改善になるアイデアであろう。
(復号化サーバとして考えれば、アクセス権はサーバとクライアント間だけの問題であるので、符号化データのアクセス権もシビアに考えなくて良さそうである。ただ、もしもこの装置をPCとかコンシュマー向けにも使いたい、となった場合には本機能の拡張版としてアクセス権対応版が必要になるだろう。)

ビッグデータとして例えば動画配信サービスであれば、似たような動画や時として「全く」同じ動画が多数あるはずで、それらを全て括り出せればものすごい容量の節約になるだろう。
動画圧縮技術次第だが、現在の方式では動画圧縮したものをストレージに格納しているはずで、圧縮動画から似た映像・同じ映像を括り出せれば良いのだが、それが不可である場合は一旦非圧縮データに展開してから映像を括り出さないといけないかもしれない。
しかし非圧縮データに展開して増える容量よりも、括り出しによって節約される容量の方が遥かに大きいだろう。
(また括り出し後に、今度は括り出し可能な圧縮方式で圧縮すれば良い。)

そもそも動画圧縮技術は、「隣接したピクセルは似通った色であることが多いはずだ」「隣接した時間では前後のフレームは連続的に移動しているはずだ(今の技術では加速度とかまで使ってる?)」と言ったアイデアで不可逆変換が主流であろう。

不可逆データ前提であるならば、括り出し時も「曖昧さ」パラメータによって、どれくらい似通っていれば同じ符号として置き換えて良いか調整ができそうである。曖昧さ:0 なら完全一致じゃないと許容しない。曖昧さを大きくするにつれて、似通った映像でも許可するが復号化した時にちょっと不自然になる、と言った感じだろう。

あと更に応用だが、動画であれば映像内部の一部の領域(静止画)についても同じアイデアが適用できそうである。つまり動画中で似通った・全く同じ静止画があるならばそこを括り出せる、と言うものである。(フレームに飾られた絵画とか)。ただしこちらは、たとえ全く同じ静止画であっても次のフレームではちょっと角度が変わったり、影がかかったりと、むしろ括り出し処理の方が難しそうである。
(余談だが動画も究極を言えば、元となった4次元データがあれば一番正確に再現できるのである。(当たり前か^^)。つまり上記で言ったフレームに飾られた絵画も角度が変わったり影が差したりと言ったことも、「絵画」データは1枚でよくて変化するのは絵画を入れているフレームの角度が変わったり、外部から影が差したりしているだけで、3Dで計算すれば良いだけの話、と言うこと。)
余談で書いたが、これも良いアイデアなので記録として残しておくこととする。
アップロードされた動画から3次元データを作成して、それを骨組みとすることで角度変化や影の差し具合などは「演算化」してしまうことによって圧縮する技術である。

なんと言うか、そこまで考えると、動画作成時に3D情報があるのであれば、わざわざ3D情報を削除することもないように思えてくる。(なんでせっかくの大切な情報をあえて削ってるの?と言うこと)。将来的には動画には3D情報もくっつけるのが主流になりそうである。

(画像認識技術でも、行き着くところは「欠落しているのは3D情報だな」と「悟った」人はたくさんいると思うのだが、画像に3D情報が付いているのが当たり前になれば「これまでの悩みは何だったの?」となるだろう。しかしこういった積み重ねれこそが技術革新なのであろう。)
(「ゲームエンジンのように画像全体をレンダリングをすると言うこと?」と思われるかもしれないが、そうではない。そんなことをしたら読み出し処理が追いつかない。
静止画や動画とレンダリングの最適解があるはずで、このアイデアをベースに最適解を探っていきましょう、と言うことである。(圧縮率、品質、エンコード負荷、デコード負荷などの総合的な最適解。圧縮技術の側面から3Dゲームエンジンを見ると、「テクスチャは容易には変わらない」と言う前提で圧縮していると解釈できたりする。テクスチャで解決できないもの、例えば髪の毛であっても最近は物凄い精度の良いモデルもあるわけで、これは言わば擬似的な近似値であり、髪の毛全てをシミュレーションしている訳ではないが、見る側としては実物と遜色のないものとして見えるため、または見えるように技術進歩してきた訳である。動画圧縮の前提として不可逆変換を前提にしている場合、つまりそれは各フレームの画像は「近似値」になっている訳であるから、本アイデアでも極端な話をすると3D化する時に髪の毛も「髪の毛近似モデル」に置き換えてしまってもいいのかもしれない。細かいパラメータは当然あると思うが。そもそも3D情報もゲームエンジンで作った場合であれば正確な情報だろうが、現実世界を撮った動画から3D情報を生成した場合は、その時点で近似値であるわけで、「近似値で良いのか?」と言う問いに対しては「では【正確な値】とは何か?」と問い直すことができるのである。それこそ映像の世界でも本当にただのレンズをそのまま撮ったのでは歪みとかぼやけとか手ぶれとか色々あるわけで、各種培われた「補正」が入っている訳である。補正をしてしまった時点でそれは既に「近似値」といえよう。物理学的な話になってきたが、実際に【正確な値】を計測することはとても大変なのである。また、もしも【正確な値】が取れたとしても、それを実際に人が「自然に」見えるようにするためには、今度は逆の手順が必要で、復元した情報を映像化する時に再度歪みとかぼやけとか手ぶれとかを結局は補正しなければならないのである。(ご存知の通り人が見る「色」の特性一つとっても奥が深い。プロから見ると「何だこの色使いは。というか何も補正してないのか?」と思われたりするのだが、では色を補正した画像は「本物」なのだろうか?)
ちょうど「本物か嘘か」と言うポイントが出てきたため、ちょっと書いておくと、
・本物を土台にして「近似」したもの
・本物のデータの一部または全てを、近似(補正)したり、モデルまたはシミュレーション(架空)データで置き換えたもの
を考えた場合、前者は本物または本物ベースのもの、
後者は嘘、そこまで明確に言わなくとも架空データで本物を模擬したもの、
と言えるだろう。
動画を楽しむ分には、そんなのどちらでも良いのかもしれないが、どの分野にも「完璧な正確性」を求めたり、求められたりする領域がある訳で、やはりどこかで真面目に議論しなければならないことである。例えば写真やビデオが証拠になったりする訳だが、担当者が気を利かせて色補正をしてしまったら、それは「本物」として扱っていいのか?と言うこと。先ほども書いたが、そもそも現代の最先端カメラでは写真を撮る時点で映像のプロによって培われた各種の補正が入ってしまっている訳で、そもそも「本物」として扱ってはいけないのではないか?と言う話になってくるのである。カメラについてはメーカーがどこで型番が何で、と言う情報で写真の特性も分かるため合わせ技で現代では「正確な」証拠として取り扱っている、と言うだけのことであろう。
しかし補正が入っていると言うことは、ある情報は強化され、ある情報は弱まったり省略されていると言うことなので、その特性を悪い方に活用されると極端な話「見えていたはずのものも見えない」写真や「見えてないはずのものが見える」写真も作れるはずである。そして現代ではそれさえも「正確な」証拠になってしまうのである!と言うこと。現代では「実際のカメラでそんな映像が撮れることは確率的には著しく低いため、取るに足らない」と割り切っているだけなのである。
上記はシビアするぎる話だが技術と共に成長していかなければならない問題である。
もう少し話を緩めると、例えば広告・虚偽広告が挙げられる。例えば本物の映像を近似値で補正するのはいいけど、シミュレーションデータに置き換えた場合、それは許されるのか?といった問題。どちらかというと倫理的な問題であろう。この辺は勿論経済の力学に沿って、Googleとかが先手を打って倫理観とかをまとめていくのであろう。(先手を打ってというか、大きいだけに何でも最初に槍玉に上げられる、と言ったほうが正確だろうか。))

3D情報ベースで書いたが、成果物ベースからもう一度見直せば、最終的な2D画像に直接関係しない3D情報は無論省略可能である。ただしこれくらい進化すれば、最終成果物として1本の動画だけにするのは勿体無い気がする。既に360°動画もあるわけだが、本アイデアは2D動画ベースなので、ちょっと違ってて、例えば2D動画なんだけどちょっとだけ視線を変えられたり、3Dカメラで撮影しなくても3D映像化ができる、とかであろうか。)

−−−−−−−−−−
ちなみに動画配信については以前に「ホログラムストリーミング」を発表済みである。

2022年7月28日木曜日

小説になるマンガ

最初はマンガなんだけど、説明文がどんどん長くなっていき、
気づいたら小説になってしまうマンガ。というアイデア。
本の枠だけ漫画になっているアイデアもアリ。
または漫画の中の人が漫画を読んでて、いつの間にかそっちがメインになるアイデアもアリ。
(くだらないけど、面白いのでアイデアとして残しておく)

2022年5月24日火曜日

Unreal Engine 5でAndroidパッケージ作成 on MacBook Pro M1

MacBook Pro M1上のUnreal Engine 5でAndroid用パッケージ(apk)を作成する環境を構築した。
その時に発生したエラーと対処法について。
※最後に詳細を書いてますが、エラー②についてはWindowsユーザの方も参考になるかも知れません。

【環境】
MacBook Pro M1 Pro (2021年モデル) macOS Monterey
Unreal Engine 5.0.1
Android Studio Chipmunk | 2021.2.1 ※Android Studio Bumblebeeでも同じだと思う。

【経緯及びエラー内容】
Unreal Engineの以下のページを参照すると、「Android Studio version 4.0」とか古いAndroid Studioしか正式には対応してなさそう。

実際には、最新の「Android Studio Chipmunk」でもできたのだが、
正式手順ではないため、あくまでも自己責任でお願いします。

環境的には、Android Studio Chipmunkインストール済みの環境で、FlutterでAndroidアプリ開発を行なって、アプリをGoogle Play Storeにリリースまでしている環境。つまりそれまではUnreal Engineは入れてなかった環境にUnreal Engine 5 を入れた状態。(なのでAndroid Studio version 4.0とか古いものは入れたくなかった。)

よって、上記リンクで言うところの
1.Android Studio をインストールする
2. Android Studio を設定する (初回ユーザーの場合)
※2.10 Android SDK Command-line Tools についてもインストール済みだった。
はスキップして、
3. Setting Up Android NDK
から実行。
なお、mac上のSetupAndroid スクリプトの場所は以下。
/Users/Shared/Epic Games/UE_5.0/Engine/Extras/Android/SetupAndroid.command

【エラー①】
SetupAndroid.command  67行目あたりで、JAVA_HOMEを設定しているが、これがAndroid Studio 4の古い設定(Java 1.8用)になっている。新しいAndroid StudioだとJava 11。
export JAVA_HOME="$STUDIO_PATH/Contents/jre/jdk/Contents/Home"

対策①: 新しいAndroid Studioの付属jdkを既にJAVA_HOME環境設定に設定済みの場合
つまりprintenvで以下の結果になる場合
> printenv |grep JAVA_HOME
JAVA_HOME=/Applications/Android Studio.app/Contents/jre/Contents/Home

この場合は、単純にSetupAndroid.commandのexport JAVA_HOMEをコメントアウトすれば良い。
export JAVA_HOME="$STUDIO_PATH/Contents/jre/jdk/Contents/Home"
# export JAVA_HOME="$STUDIO_PATH/Contents/jre/jdk/Contents/Home"

対策②: JAVA_HOME環境変数が未設定の場合
この場合は、SetupAndroid.commandのexport JAVA_HOMEのパスを修正すればよい。
export JAVA_HOME="$STUDIO_PATH/Contents/jre/jdk/Contents/Home"
↓
export JAVA_HOME="$STUDIO_PATH/Contents/jre/Contents/Home"

※なお、SetupAndroid.commandを実行すると、
SetupAndroid.command: line 20: rem: command not found
が出力され、実際にスクリプトを見てみると確かにrem、つまりDOSコマンドの「コメントアウト」キーワードが使用されている^^ しかしエラーで止まるわけでもなくスルーされるだけなので気にしなくて大丈夫(後でEpicに教えるだけ教えておこう^^ Unreal Engine 4.x の頃からこのままだっただろうし、ずっと放置されてきたのだろうから、Mac + Unreal Engine + Android開発はものすごくマイナーなのだと、逆に知ることができるのである^^)

P.S. 2022.10
Unreal Engine 5.1.0 (現時点ではPreview版) にて、上記remは修正されました!よかったよかった👍
rem hardcoded versions for compatibility with non-Turnkey manual running
↓
# hardcoded versions for compatibility with non-Turnkey manual running


【エラー②】
上記修正をして、再度SetupAndroid.commandを実行すると今度は以下のエラーが発生。
Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/annotation/XmlSchema

色々調べたところ以下のようにSetupAndroid.commandを修正すればよかった。
(83行目あたり) 
(修正前)
SDKMANAGERPATH="$STUDIO_SDK_PATH/tools/bin"
if [ ! -d "$SDKMANAGERPATH" ]; then
        SDKMANAGERPATH="$STUDIO_SDK_PATH/cmdline-tools/latest/bin"
        if [ ! -d "$SDKMANAGERPATH" ]; then
                echo Unable to locate sdkmanager. Did you run Android Studio and install cmdline-tools after installing?
                ${PAUSE}
                exit 1
        fi
fi

↓
(修正後)
#SDKMANAGERPATH="$STUDIO_SDK_PATH/tools/bin"
#if [ ! -d "$SDKMANAGERPATH" ]; then
        SDKMANAGERPATH="$STUDIO_SDK_PATH/cmdline-tools/latest/bin"
        if [ ! -d "$SDKMANAGERPATH" ]; then
                echo Unable to locate sdkmanager. Did you run Android Studio and install cmdline-tools after installing?
                ${PAUSE}
                exit 1
        fi
#fi

つまり、使用するsdkmanagerが違っていた問題。(これもJava 8 → 11 問題か)
$STUDIO_SDK_PATH/tools/binの方をコメントアウトして、追加で入れたCommand Line Toolsの方を使うように修正すればエラー発生しなくなった。

ーーー
エラー①のJAVA_HOMEについては、Windows用とMac用とで、JAVA_HOME環境変数の判定処理が異なっている。
Windows用(SetupAndroid.bat): 最初にJAVA_HOME環境変数が定義されてるかチェック
Mac用(SetupAndroid.command): 最初に強制的にJAVA_HOME環境変数を定義(export)

ただし、エラー②については、Windows用とMac用とで同じ処理内容だったため、エラー②の問題についてはWindowsユーザの方も参考になるかも知れない。
ーーー

【エラー③】
これで再度Unreal Engine 5 でAndroidのパッケージ作成( Platforms → Android → Package Project)を行うと、最後のapk作成部分で以下のエラーが発生する。
…
Making .apk with Gradle...
To honour the JVM settings for this build a new JVM will be forked. Please consider using the daemon: https://docs.gradle.org/6.1.1/userguide/gradle_daemon.html.
Daemon will be stopped at the end of the build stopping after processing

FAILURE: Build failed with an exception.

* Where:
Settings file '/プロジェクトフォルダ/Intermediate/Android/arm64/gradle/settings.gradle' line: 9

* What went wrong:
A problem occurred evaluating settings 'app'.
> AFSProject/gradle.properties (No such file or directory)

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

対応方法としては、上記* Where: に書かれているsettings.gradleファイルをエディタで開き、以下の修正をしてファイルを保存する。
new File('xxx')
↓
file('xxx')

※「new F」を「f」に置換すると簡単。
settings.gradleファイルでは「new File('xxx')」を使ってる箇所が8箇所あるので、8箇所とも修正する。

※Unreal Engineしか知らない人からすると「Gradle」が突然出てきて「何だそれは?」と思われるかもしれないが、AndroidとかJavaとか開発してる人からすると日常的にお世話になっているシロモノ。AndroidとかJavaに詳しい人に聞いてみましょう。

エラー内容としては、gradleで「new File('xxx')」の書き方をすると、ビルドフォルダからの相対パスではなく、gradleデーモンのワーキングディレクトリからのパスと解釈されてしまうらしく、よって「AFSProject」という親フォルダが存在しないので、「gradle.properties」ファイルも作成できませんよ、というエラー。
なお、gradleデーモンのワーキングディレクトリ及び実際に作ろうとしてたファイルパスは私の環境では以下だった。
/Users/user_x/.gradle/daemon/6.1.1/AFSProject/gradle.properties
よってこれを「file('xxx')」関数にしてあげれば、ビルドフォルダからの相対パスとして正常処理できるようになる。
※ただしこれもgradleというか、Android Studioに紐づいたgradleのバージョンの問題かも知れない。(流石に一度も動かないスクリプトを上げるわけないと思うのでAndroid Studio 4ではうまく行くのだろう。でもgradleバージョンによってnew File()の起点が変わるのは結構破壊的変更なので、gradleの環境周りとかもっと深い話かも知れない。要はその辺の微妙なところがバージョンの違いでうまく噛み合っていないっぽい。)

P.S. Gradleリファレンスで以下を見つけた。

やはりnew File()だとCurrent Working Directory(CWD)からの相対パスになってるとのこと。そうすると、Android Studio 4 バージョンだった時の可能性としては以下があげられる。
可能性①: 以前のgradleバージョンではnew File()もfile()同様、ビルドフォルダからの相対パスになっていた。(つまりどこかでnew File()の破壊的変更があった。)
可能性②: gradleバージョン差異の影響で、change directory(cd)が処理されておらずCWDが変更されてなかった。(特にエラーも発生せずに)。またはgradleのchange directoryの解釈が変わったりしてCWDとしては変わっていなかった。
可能性③: やっぱりAndroid Studio 4でもこの箇所でエラーになる^^(つまり一度も動いてないスクリプトだった^^)

可能性は絞れたが、ここではそこまでは追わない。。



次の手順が注意が必要であるが、上記修正&保存をしたら、ターミナルを開いて自分でgradleを動かしてあげる必要がある。
理由:UE側でAndroidのパッケージ作成( Platforms → Android → Package Project)を行うと、修正したファイルが毎回上書き更新されてnew File('xxx')に戻ってしまうため。ちょっとだけ追ってみたところ、該当settings.gradleはUE側のスクリプトで生成しているようです。
> cd /プロジェクトフォルダ/Intermediate/Android/arm64/gradle/
> ./gradlew assembleDebug
「assembleDebug」はデバッグ用apkを作成するタスク(コマンド)。目的に合わせてタスクは変えて下さい。タスク一覧は「./gradlew :tasks」で確認可能。どのタスクを使うとかはAndroid Studioの話になってくるので、Android Studioリファレンスを参照して下さい。

これで無事にapkが作成できた!ただしapk出力パスはUnreal Engineで指定した場所ではなかったため注意。私の環境の場合は以下になっていた。
/プロジェクトフォルダ/Binaries/Android/test_app-arm64.apk
※apkの出力先が異なっているため、手動でgradlewを実行する時のパラメータが足りてないかも知れない。assembleDebugしか試してないが、Play Store用にApp Bundleを作成する場合は証明書が必要となるため、その辺のパラメータもUnreal Engine側で設定した値は正常に引き継がれないかも知れない。ということで、App Bundle作成時はもっと複雑な問題が出てくると思われる。gradlewの引数を含めた実行コマンドが不明なので何とも言えないが、Unreal Engine側で動的に渡している場合は、もう人の手で補えるレベルのものではないかも知れない。(最後に結論として書くが、素直にAndroid Studio version 4を別途入れた方が良いかも^^)

これで、Androidエミュレータとか実機Android端末をつないで、adbコマンドでインストールすれば実行可能!
> cd /プロジェクトフォルダ/Binaries/Android
> adb install test_app-arm64.apk
Performing Streamed Install
Success

※ちなみにUnreal Engineでデフォルト設定でAndroidアプリ作って動かした時に「No Google Play Store Key. No OBB found...」エラーが発生する問題があるのだが、それはまた別問題なので、各種Q/Aサイトをご参照ください。



私の場合は、Unreal Enginの以下の設定をして上記エラーが発生しなくなり、アプリ起動に成功した。
Project Settings
 Platforms
  Android
   Package game data inside .apk? : Yes/Checked
   Disable verify OBB on first start/update. : Yes/Checked
   Force small OBB files. : Yes/Checked

 Project
  Packaging
   Full Rebuild : Yes/Checked
上記変更後は、Unreal Engine側で再度Android Package Projectが必要。そうすると、settings.gradleは毎回上書きされてしまうため、再度settings.gradleでエラー発生するので、「new File()」を書き換えて、手動でgradle実行となる。

もう一つの注意点としては、「adb install」する前に対象Android端末からは一回アプリをアンインストールしておいた方が良い。
(私は最終的に色々試したapkで、上書きadb installだとダメだったが、アンインストール後に全く同じapkで「adb install」したら正常起動できた。なので、Unreal Engine側の設定で一体どの項目がクリティカルだったのかは不明。)

こちらが実際にAndroid端末で動作したテストアプリの画面キャプチャー。黄色いでかいキャラクターは世界的人気ゲーム「ROBLOX」の「NOOB(ヌーブ)」です^^一体何のゲームを作ろうとしてるのか?って感じですね。

という訳で、無事にMac + Unreal Engine 5.0 + Android Studio Chipmunk でAndroidアプリのパッケージ作成が出来たわけだが、こんなに煩雑なことをするのなら、素直にAndroid Studio version 4.0 を入れた方が手っ取り早そうである^^という結論に達した。
(おそらく)Unreal Engine側としても最新Android Studio対応はしてくれてる/念頭にはおいてくれてると思うので、最新Andorid Studio連携はそれを待っても良いかも知れない。(最初に載せたリンクも「Unreal 4.25 以降は」となっているが、まだUnreal Engine 5.0 専用のページはない。)

ーーー
P.S. 2022.10 再度リンク先ページを確認したところ「Unreal 4.25 以降は」の表記が消えていた。そして内容はAndroid Studio 4.0のままだった。つまりUnreal Engine 5.0 ではやはりAndroid Studio 4.0のまま据え置く結果になった模様。。「最新Andorid Studio連携を待ったほうが良いかも」と書いたがUE5では可能性が薄れ、当分先になりそうなので、諦めて公式リファレンス通りAndroid Studio 4.0 を使いましょう!^^
ーーー


「どうしてもAndroid Studio環境を汚したくない!」という方は参考にしていただければ幸いである。(Unreal Engine側でNDKとか入れるので影響は少なからずあるのだが。。)

あと何点か、Mac + Unreal のマイナスポイントを上げておく。
・そもそもWindows用にパッケージ作成できない(ですよね?ちょっと調べただけだけど。どうしてもDirect Xの壁があるからそりゃ無理なのかな?逆にWindows版Unrealだとios版が作れる?ので羨ましい。)
・Unreal Engineライブラリで使えるものが少ない。ほとんどWindows用ばかり。UE5リリース時に話題になってた映画Matrixの「Cityサンプル」も、Microsoftの音響システム「 Project Acoustics」 もWindows版だけとか。せっかく「いいな」と思ったものを見つけてもMacだと試せない。。MacではNatiteは対応されていないし対応予定もないので、Cityサンプルを試すのはやはり無理っぽい。
There is no Mac OS support for Nanite, nor is any likely in the future due to 
graphics API limitations.
(Google翻訳)
Nanite に対する Mac OS のサポートはありません。また、グラフィックス API の制限により、
今後もサポートされる可能性はありません。

NANITE FOR EDUCATORS AND STUDENTS より抜粋
※Mac環境&UE5.1 で影が以前より濃くなる現象に直面した。根本解決ではないが、とりあえずの回避策を見つけたので、こちらを参照。

ーーー
そして、こちらもそもそも話だが、ゲームを「遊ぶ」側としてもEpic Games StoreのゲームはWindows版ばかりである。

ということで、本格的にゲーム開発する人は当然Windowsマシンで開発するのだろう。
「Windowsのゲームを本格的に開発したいので、Macを買いました」という人がいたら「なんでそうなるの?」となるだろう。
ゲーム + Mac + Unreal はモバイルゲーム開発とか、またはMacが好きでMac用ゲームを作りたいとかのパターンが考えられる。しかしこれも現時点での私個人の主観でしかないし、最近ではモバイルからPCへの逆パターンもあったり、MacからWindowsとかの流れもなきにしもあらずだと思う(少なくともJavaのEclipseとかか始まり、今ではAndroid Studio然りUnityやUnreal Engine然りというように「IDE」はWin&Mac両対応が当たり前になっている)ため、これもまた自己責任でこの辺の動向はウォッチしていって自分に合ったやり方・環境を見つけてくれればと思います。
(会社とか組織規模で考えれば、会社内にWindowsマシンもある訳で最終的なapk(aab)出力はWindows環境でやれば良い訳で、別にMacでapk(aab)出力を出力することにこだわることはないのかも知れない^^
と、そこまで話が遡ってしまうと、今回の話も、またUnreal EngingeがMac用にもAndroidパッケージ出力方法(手順)を作っている意味も無くなってしまうので、私も含めて「それしかない環境」でやっている人もいる訳で、また大きく言えばプラットフォームの(純粋な意味での)垣根を越えるという点に寄与しているという点において、意味はあるのであろう。※「純粋な意味での垣根を越える」とは、お互いにWin-Win関係になれる、という意味。
ちょっと湾曲的すぎて何を言ってるのかわけがわからないと思うので、簡単にいうと「クリエーターからするとEpicとAppleの訴訟なんて知ったこっちゃなくて、せっかく素晴らしい3DCGエンジンがあるのだから、グラフィックとかアート分野に強いMacでも使わせて欲しい!」と言ったところだろう。それこそFortniteとかちゃちい話(失礼!)ではなく、Win-Winになれると思うのだが。。
かと言って、実際問題としてこのように影響があるのだから、訴訟の話も無視するわけにはいかず、話はぐるぐる回るわけである。。)

2022年4月22日金曜日

無駄に段落分けしたサイト

最近調べ物をしていると、無駄に段落分けされたサイトがよく出てくる。
おそらく皆さんも同じことを感じているだろう。

内容的には1つの段落で十分かけることであるのに、わざわざ章立てしていたりして
いくら下に進んでも答えが出てこない。
(挙げ句の果てに「続きは次ページで」になってたりする。そんなに壮大なことを書いているのだろうか?その壮大さに気付けずにすいませんとでも言って欲しいのだろうか?)

これがインターネットの発展に寄与していると言えるのか?
その判断はGoogleなど検索サイト次第であるが、ユーザのためを思って
あまり上位には持ってきて欲しくないものである。
(最低限そのページを作った人は「素晴らしく人類に寄与しているサイトだ!」と思ってるはずだが、本当に自分の目で見て確かめてそう思っているのだろうか?)

ーーー
一応上記のようなサイトをフォローしておくと、そのサイトの規則的に
必ず章立てすることとか決まってて、書いてる人は「しょうがなく」
書いているのかもしれない。
ではそのサイトの管理者はなぜ、どんなに薄い内容でも無駄な章立てを
強要しているのか、となってくるが、もしもそれが広告表示回数を上げるため
であるならば、それこそGoogleなど広告提供側から厳しくチェックされる
ことになるだろう。
(ある意味自業自得で放っておけば勝手に検索順位は下げられそうなので
 まぁいいか。。)

ーーー
P.S. 2022.8
ついにGoogleが検索にておいて、低品質な結果をあまり表示しないように更新するとニュースが出てました。ようやく私を含めた皆さんのお怒りのようなものが伝わったんですかね^^
(本当はGoogleが主体的に日々検索エンジンを「有益な」ものにするよう改善してるのだと思いますが。)

これで広告収入のために頑張って章分けをしていたサイトは上位には出てこなくなると思います。まぁ彼らも「こんなウマイことはない」と思いながらやってたでしょうから、短期間でも稼げてよかったのではないでしょうか?
(ただし、新しいエンジンの特性を見抜いて対処するというイタチごっこは続くかもしれませんが。。)

2022年4月19日火曜日

天の川銀河・ミルキーウェー銀河・Milky Way Galaxy について

天の川銀河・Milky Way Galaxy というのは、地球人が我らの銀河を
内側から見た時に白い帯が天の川のようだからそう呼ばれているためである。

一方で我らの銀河以外の銀河については、地球から見えた時の色や形で
愛称をつけたりしている。

そこで、将来的なことを踏まえて、この天の川銀河・Milky Way Galaxy という
名称について考察しておこう。

簡単に考えると次の2段階。
①我らが銀河内の別の生命社会が存在したとして、彼らが我らが銀河を何と呼んでいるか。
彼らと我ら(地球人)で名称を統一する話になった場合に何になるか。
我ら地球人は、地球上で見ると、我らが銀河は白く見えるのだが、彼らの環境だと違う
ように見えてまた違った発想の呼び方かもしれない。

②我らが銀河の別の生命社会が存在したとして、彼らが我らが銀河を何と呼んでいるか。
彼らと我ら(地球人)で名称を統一する話になった場合に何になるか。

①で地球外の生命社会が存在しなかった場合とか、存在したとしても諸事情で①は
スキップするかもしれない。
また、いずれ②まで考慮することになる訳であるから②の方向で考えてしまった方が
手っ取り早くもある。
もう一点、「天に見える川」とか、「空に見えるミルクのように白い川・道」というのは地球以外の星でも同じような呼び方をしている可能性が高くて、①とか②とかになった時に彼らと我らで呼称が被ってしまうと思われる。

という訳で、他の分野でもそうだが、あくまでも「客観的に」自分を見つめて
愛称をつけた方がよさそうである。

果たして我らが銀河は、外から見るとどのように見えるのだろうか?

ーーーーーーーーーーーーーーーーーーーーーーー
かなりの取り越し苦労ではあるが、一方で最近は「物理的にそこへ行くことよりも
そこに行ったことを仮定する」方が重要で有用であると、人類は気づき始めているため、
意外と早くこの点も考慮される日が来るかもしれない。

ーーーーーーーーーーーーーーーーーーーーーーー
客観的な特徴とは何だろうか?
例えば銀河が可視光領域で全体的に赤っぽいのであれば「赤い」のが特徴。
しかしその赤色の原因は、その銀河が含んでいる物質的なものなのか、赤方偏移によるものなのか。
前者はその銀河の特徴となり得そうだが、後者はやはり観測される側と観測する側という相対的な要因を孕んでしまう。

特徴を述べる時にはもっぱら視覚情報によるものが多い。
これは視覚情報が情報として多く、特徴を共有するのに適しているからとも言えるだろう。
しかしこれまでの考察の通り、銀河レベルで「公平な」特徴を言う時はどうやら限界がありそうである。
現在までのところは共有相手は地球内であるため、地球から見える色とか形で一向に問題はない。※形についても地球から見た角度だと、そう見えるだけであって、地球と反対側の人(宇宙人)に伝える時点で「特徴」情報としてふさわしくないことに気付く。

よって「公平な」特徴は、極論すればその銀河内の全ての情報を元に導き出されるものの方が良さそうである。
すでにここまでの話でも端々に出てきているが、特徴とは別個体との情報共有とか、または対象を「大雑把に」把握するためのものであり、つまり外部からの「観測」によるものである。観測で使われるのは地球人の場合は所謂五感(視覚、聴覚、触覚、味覚、嗅覚)であるのだが、宇宙生命体ではもっと多くの感覚があるかもしれない。(例えば重力波も知覚できる感覚など。これは突拍子もないアイデアで全くの空想であるが、例えば惑星とかそれこそ銀河規模の生命体が「いた」として、その生命体は一体何を知覚するのだろうか。地球上の生物はなぜ知覚するかというと生命維持が大きな目的、最初の出発点になっているのだが、宇宙規模の生命体は純粋に知覚することを目的としてそうである。生命の何たるかが解明されて、人工的に生み出すことができるとすれば、それら宇宙規模の「感覚を持った生命」も生成されうる、と言う思考実験。)

脱線してしまったが、銀河の特徴を抽出する際に、観測者の(地球人でいうところの)五感の情報をフルに使って特徴抽出した方が良いだろう、ということである。少なくとも公平度合いは増すだろうということ。

得られた情報を3次元なり4次元空間にプロットしてみて、座標をぐりぐり回して眺めたりして、どの方角から見ても、というか「全体」として何かにそっくりだったとすれば、その名前を拝借するとかが考えられる。例えば3Dに可視光または何かの電磁波をプロットしてぐりぐり見てみたら、地球上の蝶にそっくりだったとすれば「地球上の蝶」銀河と名前をつける、とかである。ここでの例は結局視覚による認識になってしまっているが、あくまで分かりやすい例え話のためである。しかし人が知覚できない電磁波領域の特徴を掴んだとしても、共有相手も人と同じ可視光領域しか持たない生物だったとしたら、果たして伝えるときの「特徴」として相応しいのかどうか?という問題点もある。

そもそもの話に戻り「そもそも特徴というのは個体間の情報共有のためのものであり、厳密な意味はないので、考えるだけ無駄」と言うのであれば、振り出しに戻るのであるが、そうすると今度はやはり来るべき銀河時代にどうやって情報共有するのか?と言う話に戻るのである^^
「そういった時代になれば、その時の人が勝手に色々考えるだろう」と言うのであれば、最初に書いた通りのただの取り越し苦労と言うだけの話なのであるが、だからと言って人のこういった知的探求は誰にも止められないのである。と、体裁よく話をまとめて終わりとしよう。

ーーーーーーーーーーーーーーーーーーーーーーー
やはりもう少しだけ書いておこう^^
「地球人の所謂五感」と書いたが、大抵の場合は系の中心に恒星があってそれが重要なエネルギー源になっていたり、また現代の科学情報ではどうやら生命の起源には「水」が重要そうで液体としての水が大量に存在し得る条件が大切らしい。そこで「生命」という枠だけで、しかも「知覚」とうことだけで考えれば、もしかすると地球外・太陽系外・天の川銀河外の生命体もある程度は同じような感覚を発展させるのかもしれない。(もちろん地球上にも深海には視覚は弱まって触覚とか別器官で生存する生物もいると言う点は考慮が必要。)

また、逆に言うと生命というものは自分が生存する環境に適するように、つまり重要な情報を知覚できるように進化の発展を遂げていると言えるわけであるから、その環境の特徴とはつまりその環境に住む生物がどういった知覚器官を備えたり発達させているかを知ることで分かる、とも言えるだろう。

2022年3月23日水曜日

MacBook Pro M1 Pro (2021年モデル) に買い換えた話 (新旧比較表付き)

と言うわけでついにMacBook Proを2009年モデルから2021年モデルに買い換えた!

「どう言うわけか?」と言う方はこちらをどうぞ。

せっかくなので比較しておこう。


BeforeAfter
ModelMacBook Pro
13-inch, Mid 2009
MacBook Pro
14-inch, 2021
Display13.3インチ
クリアワイドスクリーンディスプレイ
14.2インチ
Liquid Retina XDRディスプレイ
CPUIntel Core 2 Duo
2.26GHz
Apple M1 Pro
10 Cores
GPUNVIDIA GeForce 9400M 256MBApple M1 Pro
16 Cores
Memory2GB DDR3
→ 8GBに交換
 2016年 ¥9,300
16GB
LPDDR5
Storage160GB HDD
→240GB SSDに交換
 2016年 ¥10,260
1TB SSD
Battery60Whリチウムポリマーバッテリー70Whリチウムポリマーバッテリー
Height2.41 cm1.55 cm
Width32.5 cm31.26 cm
Depth22.7 cm22.12 cm
Weight2.04 kg1.6 kg
Keyboard"Scissor" Keyboard(※1)バックライトMagic Keyboard, Touch ID
CameraiSightカメラ1080p FaceTime HDカメラ
Wi-Fi802.11n/a/b/g802.11ax Wi-Fi 6
BluetoothBluetooth 2.1 + EDRBluetooth 5.0
Power Adapter60W MagSafe電源アダプタ96W USB-C MagSafe 3電源アダプタ
USBUSB 2.0ポート(最大480 Mbps)×2Thunderbolt 4 (USB-C)ポート x 3
Display OutputMini DisplayPortHDMIポート
Audio I/O3.5mmヘッドフォンジャック3.5mmヘッドフォンジャック
SD Card SlotSD Card SlotSDXC Card Slot
CD Drive8倍速SuperDrive
(DVD±R DL/DVD±RW/CD-RW)
-
FireWireFireWire 800-
※1 … キーボードも Scissor Keyboard (シザーキーボード) から Butterfly Keyboard (バタフライキーボード) の一悶着があって、Scissor Keyboardが復活&改良されてMagic Keyboardとなったらしい。もちろん私はButterfly Keyboardは知らない…
バタフライキーボード: 2015年〜2019年

2009年モデルのスペック及びマニュアル
2021年モデルのスペック及びマニュアル
※マニュアルがかなり簡略化された^^

この後に写真比較も載せるが、昔の13インチモデルが今の14インチモデルと同じ大きさなのも面白い。

2016年にメモリ増強(¥9,300)とSSD化(¥10,260)合わせて¥19,560で6年も延命できたのだから安上がりであった。(というか使おうと思えばまだまだ使える!)
メモリは最初の2GBのものを外して、4GBを2枚挿しにした。
当時の記憶では検索をミスったのかメモリは最大で4GBまでと勘違いしていた。(MacBook 13-inch late 2009モデルと勘違いしてた?)
勘違いしていたため8GBまで乗せれるのか色々検索し、どなたかが8GBでもちゃんと認識されたとか見つけて、大丈夫ということを確信した上で8GBにした様な気がする。証拠を載せておく。(前記事の通り、2009年モデルは OS X El Capitan (10.11)。About This Mac 画面は当時からあまり変化していないことが分かる。)

P.S.2022.10.9
私が「About This Macが少なくとも2009年から10年以上も変化していない」と言ったことから、ついにmacOS Ventura 13.0 にて変更されました!私の指摘がよほど気になったようですね^^またはMacBook Pro 2009年モデルを10年以上も大切に愛用した私の意見を尊重しれくれたんですね。(そんな訳はない。。VenturaにてSystem Setting(システム設定)が ios 風に統合されたので、その一環でAbout This Macも見直されたのでしょう。)



それでは比較写真に移ろう。
トップ 左:2009年モデル 右:2021年モデル※プラスチックカバーを付けてます。


フロント 下:2009年モデル 上:2021年モデル
2009年モデルについては、右から赤外線レシーバ、スリープインジケータ
2021年モデルがコンパクトになった。2021年モデルの方が軽いのだが、手で持って比較すると2021年の方が「詰まってる感」がする。
本記事を書いててわかったが、2009年モデルには赤外線レシーバがあったんだ。。この機能だけは使わずじまいだった。。

右側面 下:2009年モデル 上:2021年モデル
ポートは前方から
2009年モデル:盗難防止用ロックスロット※USB-Cではありません!, CDドライブ
2021年モデル:SDカードスロット, USB-C, HDMI
そう言えば2021年モデルには(というかいつからか)、盗難防止用ロックスロットが無くなった気がする。店舗展示とか会社の事務所に置きっぱなしにする場合にワイヤーチェーンで机とかに結び付けて盗難されない様にするものだが、この辺にも世界標準的に考え方の変化があったのだろうか?ISOとかでリスクアセスメントを理詰めでやると大抵はワイヤーチェーンなどに行き着くのだが、「現実問題との乖離」問題もあるわけで、世界標準もこの辺の乖離に一歩踏み込んで次のレベルの現実解まで考察し始めてくれたのであれば幸いである。
(現実問題との乖離として、何よりもズレているのは、大盗賊であれば当然ワイヤーカッターを持って盗難に来る、ということである^^大盗賊と言わずとも、よほど頭が弱くて世情を知らない盗賊でもなければ、「ワイヤーチェーンで結ばれてるかも知れないからワイヤーカッターも準備しておこう」となると思う。そうするとワイヤーチェーンの主たる目的はむしろ「抑止力」なのかも知れない。)


そして何よりもCDドライブ!当時インターネットは普及していたとはいえソフト購入時の主なメディアだったり、マシン故障時のリカバリメディアだったりした訳で「必要」だったのである。
ソフト購入について、多分どこかでちゃんと考察されているのだろうが、また私を含め一般コンシューマーの多くも心に思ったことだと思うが、スマホが世に出てAppleのApp StoreやGoogleの Play Store が出来てお客さんはバンバンアプリを購入する様になって、AppleとかMicrosoftは「あぁ何でもっと前からPC版Storeを真剣に作らなかったのだろう」と思っていることだろう。順当に考えるだけならスマホ効果でPC側に逆輸入しただけとも捉えられる。まさに黎明期である。

マシン的な話に戻すとこの物理的稼働装置を無くせたことは大きい。後で書こうと思ったがここで書いてしまうが、また前記事でもちょっとだけ触れたが、ポートを最小限まで切り詰めたり、バタフライキーボードにしたり、ファンクションキーをTouch Barにしたりという一連の流れは「現在の技術で最小化、コンパクト化、物理稼働装置の撤去・デジタル化・仮想化をできるところまでしてみよう」的ないわば一大ムーブメントがあった気がする。「今」というのが難しく、本当の現在の最新技術であれば基盤からポートから最新のものを使えば良いのだが、世に出ているものと次世代規格が同時進行で時間は流れている。製品化するには「今」という断面を切らなければならないということ。
当時Appleが目指した「シンプル化・最小コンパクト化」も「現在」技術であれば簡単に到達できるのだろうが、目指していたことはそういうことでは無論あるまい。むしろ一回リスクを負って、シンプル化・最小コンパクト化を目指して、それを実際にやってみないとそこからの景色は見えない、という事であろう。
(世の単純比較からは「Appleは後悔して前の時代に戻った」とか散々言われているが、ここで得たAppleの知見は計り知れない。また、最大の「外せない」物理装置としてキーボードは常に念頭に入れているはずである。誰しもが憶測しただろうが、おそらくキーボードを薄くしていって、最後はスマホのように仮想キーボードでいいんじゃない?に持っていきたかったのだろう。でもキーボードは「反応(レスポンス)」「押した感覚」を人は求めているということ。かといってトラックパッドのクリックは物理的押し込みはしなくてもいいんじゃないかと思う。塩梅が難しい。まさにこういったことの積み重ねなのだろう。)

右側面 下:2009年モデル 上:2021年モデル
ポートは前方から
2009年モデル:ヘッドフォンジャック, SD Card Slot, USB 2.0 × 2, Mini Display Port, FireWire 800, Ethernet, MagSafe電源ポート
2021年モデル:ヘッドフォンジャック, USB-C × 2, MagSafe電源ポート
左右のポートを比較してみると、さすが私が買い替えるために開発された(前記事参照)だけあって、ポート構成が似ている。
・ヘッドフォンジャック復活。(あれ? MacBookだとヘッドフォンジャックは無くなったことはない?iPhoneの話か。)
・四角いUSBから、丸いUSB-Cへ。
・Mini Display PortからHDMIへ。
MagSafe電源ポートは平べったくなった。
・EthernetとFireWireが無くなった。FireWireが懐かしい。

おまけ:2009年モデルのバッテリーインジケータ
1個前の比較画像だと分かりづらいが、2009年モデル前方にはバッテリーインジケータがあった。ボタンを押すとバッテリー残量がわかる。

続いて開いた状態。

左:2009年モデル 右:2021年モデル
比較して気づいたが、トラックパッドが若干大きくなってる。

2009年モデル キーボードとトラックパッド
2009年モデルは訳あって英語配列キーボードにした。

2021年モデル キーボードとトラックパッド ※キーボードカバーを付けている。
右上の2009年モデルではCDイジェクトボタンだったところが、2021年モデルではTouch IDになった。
またキーボードの話になるが、2009年モデルの方がストロークが深いため押しごたえがある。特に矢印キーについては2009年モデルの方が使いやすい。人差し指、中指、薬指を置いた時に手の感覚でどのキーを押しているのかが分かって安心するからだろう。
2021年モデルくらい薄くなると、ちゃんと指が正しい矢印キーを押せているのか何となく不安になる。(慣れの問題かもしれないが。)
この辺の
・英数字キーは「F」と「J」に人差し指を置いたホームポジションからの相対的な感覚
というのと、
・矢印キーはゲームパッドなどと同様に指先の感覚
という点で性質が異なるということである。(人間工学メモ)

背面 左:2009年モデル 右:2021年モデル
2021年モデルにはプラスチックカバーを付けている。

せっかくなので電源アダプターも載せておく。

上:2009年モデル 下:2021年モデル
デザインやサイズは前から変わっていない。2009年モデルではコード一体型だったため巻き取り用ウィング(正式名称不明)があって便利だった。ただし写真のように巻き取った後の格好については、Appleデザイン的に合致しているかどうかは不明である。(巻き方が汚いだけ?)

プラグ部分を取り外した状態
左:2009年モデル 右:2021年モデル
プラグ部分は全く一緒のように見えた。多分2019年モデルのものは2021年モデルにもぴったりとくっ付くと思うが、壊れたら嫌なので試してない。
※写真ではプラグ部分の大きさが違うように見えるかも知れないが、被写体の置き方や角度が違うだけで、つまり私の写真の撮り方が下手なだけである。

以上が比較結果である。こんなに世代がかけ離れたマシンの比較結果内容で買い替えを検討する方はいないと思うが、読み物として読んでいただければ幸いである。

なおFlutter開発について本MacBook Proを以って、ようやく念願のiOS版もリリースすることができた!
ネットを調べるとApple Developer Program購入やアプリの審査など時間がかかると書いてあったが、私の場合は3/15 にApple Developer Programを購入実施、完了して、3/16にはApp審査も通ってリリース(App Store公開)までできてしまった!(結構最小日数記録だと思う。)
これも2009年モデルMacBook ProというApple製品を大切に使ってきたおかげであろう。

2022年3月13日日曜日

Flutter: Androidの場合、showDialog(AlertDialog)内でWebViewを使用するとボタンが見えなくなる現象の対処法

Androidの場合、showDialog(AlertDialog)内でWebViewを使用するとボタンが見えなくなり困っていたが対応できた。

Flutterバージョン
> flutter --version
Flutter 2.10.3 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 7e9793dee1 (10 days ago) • 2022-03-02 11:23:12 -0600
Engine • revision bd539267b4
Tools • Dart 2.16.1 • DevTools 2.9.2

対応前            →  対応後
 


使用しているWebView
webview_flutter: ^3.0.0
※執筆時最新バージョンは 3.0.1 

対処法
initState() に WebView.platform = AndroidWebView() を追加。
@override
void initState() {
  super.initState();

  // Enable virtual display.
  if (Platform.isAndroid) WebView.platform = AndroidWebView();
}

詳細
対応前は、ボタンは見えてないだけで、ボタンがあるあたりをタップするとちゃんとタップイベントが動作していたため、「見えてない」だけのようである。

また不思議なことに、次のページに遷移してそちらでもshowDialog()でダイアログ内にWebViewを使用しているのだが、こちらはちゃんとボタンが表示されていた。

なお、アプリ作成時(2019年3月ごろ)は、全画面ともダイアログのボタンは表示されていたため、webview_flutterをバージョン3.0.0に上げてからの症状だと思われる。

ネット上でもWebView関連の症状は結構あるようなので、その辺の問題であって、Flutterライブラリの更新はまだまだ目まぐるしい。
Flutterはその様に目まぐるしい状況なので、調査される方はあまり古い情報にハマらない様ご注意ください。(正攻法は「最新ライブラリのリファレンスを読む」ことなのだが、どうしても急いで対処療法を探すとネットに頼ってしまうこともあるかと思うため、念の為。)
(加えて言うならば、例えば.NET やJava だともう大きく変化しない箇所があって、「こういう時は、こう対応」みたいなものができていて、検索エンジンもそういったものを上位に持ってきてくれるので、古い情報でも気にせずに検索上位から当たっていく、みたいなやり方もアリといえばアリなのだろうが、マルチプラットフォーム開発の期待の星・または大本命であるFlutterはまだまだガンガン発展・進化を遂げていくであろうから、前者のやり方に慣れてしまった方は注意である。例えば.NETやJavaから、いきなりFlutter担当になった方など。「基本は本家リファレンスをあたる」という基本習慣が身について良いかも知れない。)

ちなみに、私のアプリもwebview_flutterをバージョン3.0.0にした時に、描画されるHTMLが全体的に小さくなったため、HTML側で以下を追加して対応してた。
<meta name="viewport" content="width=device-width, initial-scale=1.0">

webview_flutterバージョン3.0.0の変更履歴を見ると、BREAKING CHANGE(破壊的変更)とあって、ちょうどこの箇所が関係していたようだ。
BREAKING CHANGE: On Android, hybrid composition (SurfaceAndroidWebView) is 
now the default. The previous default, virtual display, can be specified with 
WebView.platform = AndroidWebView()
(出典: pub.dev webview_flutter)
それにしてもSurfaceAndroidWebViewがデフォルトになることで、なぜWebViewがダイアログのTextButtonに影響しているのかは不思議である。(私はこの症状にはなったことはないが、ネット上に「showDialogでWebViewを使うとWebViewがダイアログをはみ出す」とかもあったので、やはりWeb画面は色々できるので強力であり特殊なのだろう。)

※そもそもアプリの更新を半年くらいしてなかったら、DartがNull Safety正式版になってたりとか、ライブラリもWebView含め、Firebaseとか結構な変更があったので諸々対応して大変だった^^
 みなさんも放置しすぎない様に注意しましょう!(バージョンアップ対応に追われて、なかなかやりたかった更新作業に辿り着けない。。。)


(おまけ) コード抜粋(buildの骨組みだけ)
※Null Safetyは突貫で直しているので、_doShowDialog の String? contentStr は、String contentStrでいいんじゃないか、とかはご愛嬌^^
①問題が発生した画面
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(_appTitle),
          actions: <Widget>[
            PopupMenuButton(
              itemBuilder: (BuildContext context) {
                return [
                  PopupMenuItem(child: Text(AppLocalizations.of(context).aboutXxxTitle), value: 1),
                  PopupMenuItem(child: Text(AppLocalizations.of(context).aboutYyyTitle), value: 2),
                ];
              },
              onSelected: (menuId) {
                // ダイアログ表示
                if (menuId == 1) {
                  _doShowDialog(AppLocalizations.of(context).aboutXxxTitle, AppLocalizations.of(context).aboutXxx);
                } else if (menuId == 2) {
                  _doShowDialog(AppLocalizations.of(context).aboutYyyTitle, AppLocalizations.of(context).aboutYyy);
                }
              },
            ),
          ],
        ), // AppBar
        body: SafeArea(
          ...(省略)

  // ダイアログ表示
  _doShowDialog(String title, String? contentStr) {
    showDialog(
      context: context,
      builder: (_) {
        return AlertDialog(
          title: Text(title),
          content: Container(
            width: MediaQuery.of(context).size.width - 10,
            height: MediaQuery.of(context).size.height - 350,
            // 以下のWebViewは実際は別クラスにしてます。リソース(assets)テキストを表示するだけのWebView。
            child: WebView(
              onWebViewCreated: (WebViewController webViewController) async {
                // return the uri data from raw html string.
                String htmlString = '<!DOCTYPE html><body>' + contentStr! + '</body></html>';
                await webViewController.loadUrl(Uri.dataFromString(htmlString, encoding: Encoding.getByName('utf-8')).toString());
              },
            ),
          ),
          actions: <Widget>[
            // ↓これが見えなくなったボタン
            TextButton(
              child: Text("OK"),
              onPressed: () => Navigator.of(context, rootNavigator: true).pop(context), // これでダイアログが閉じられる
            ),
          ],
        );
      }
    );
  }

②問題が発生しなかった画面
  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Expanded(
            child: StreamBuilder<QuerySnapshot<Map<String, dynamic>>>(
              // ページデータを読み込む
              stream: _pageData,
              builder: (BuildContext contextPageData,
                AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>> snapshot) {
                  if (snapshot.hasError) {
                    return Center(child: Text('Error: ${snapshot.error}'));
                  } else if (snapshot.connectionState == ConnectionState.none ||
                    snapshot.connectionState == ConnectionState.waiting) {
                    // ロード中
                    return _getLoadingText();
                  } else if (!snapshot.hasData) {
                    return _getLoadingText();
                  }

                  switch (snapshot.connectionState) {
                  case ConnectionState.waiting:
                    return _getLoadingText();
                  default:
                    // ページ情報
                    List<DocumentSnapshot<Map<String, dynamic>>> pages = snapshot.data!.docs;
                    return DefaultTabController(
                      length: pages.length,
                      initialIndex: _currPage!,
                      child: StatefulBuilder(
                        builder: (BuildContext contextTab, setState) =>
                          WillPopScope(
                              onWillPop: () {
                                // 前画面へ戻る
                                Navigator.of(context).pop();
                                return Future.value(false);
                              },
                              child: Scaffold(
                                appBar: AppBar(
                                  title: Text(widget.textDoc.data()!["title"]),
                                  actions: <Widget>[
                                    IconButton(
                                      icon: const Icon(Icons.info, color: Colors.white, size: 30,),
                                      onPressed: () {
                                        // 説明をダイアログ表示
                                        _doShowDialog(widget.textDoc.data()!["title"], widget.textDoc.data()!["text_info"]);
                                      },
                                    ),
                                  ],
                                ),

おまけなので、アプリの詳細は割愛するが、
①問題が発生した画面 では、appBarまたは、bodyの情報ボタンからダイアログを表示している。
②問題が発生しなかった画面 では、appBarからダイアログを表示している。
やっていることは、_pageDataとして外部からページデータを取得して、StreamBuilderでタブに表示している。そこそこありがちな構成だと思う。

構造としては、①だと Scaffoldだけだが、
②だと SafeArea → Expanded  DefaultTabController  StatefulBuilder  WillPopScope  Scaffold
となっており、この辺の構造も関係しているのだろうか?
ネット上にもScaffoldがどうのこうとと書いてあった様な。。。