[Unity] 60fps 60フレームレートでの瞬間的なフリーズと incremental GC

03-30,2024

60fps固定のゲームなんか作ることは永久にないだろうと思っていたのに
必要なシチュエーションが生まれてしまい、
それをきっかけにして、今回の問題にぶちあたりました。


・問題


通常は問題なく動作しますが、
1分に1回くらい、瞬間的にフリーズし、またすぐに動き出すという現象が発生しました。
止まっている時間はわずか0.1秒くらい。
しかし、60fpsだと、それが無茶苦茶目立ちます。


60fpsは、厳密には、その刹那の隙間を人間の目は認識できないレベルですが、
俯瞰した時の全体像の雰囲気は、滑らかさとして人間の目にもはっきりと分かります。

また高速で移動するオブジェクトの場合は、fpsが低いと、
映像の中のヘリコプターの羽と同じように、二重や三重になって目に見えます。
しかしfpsが高ければ、そのダブりが、滑らかな連続体のように認識できるというメリットがあります。

が、

Unityは、ちょっとしたことですぐにメモリゴミが発生しやすく、
また、そのメモリゴミをヒステリックに解消しようとする思想があるのか
小規模のプログラムでも、
ゴミを解消しようとする内部プログラムが動き出します。

今回の瞬間的なフリーズは、これが原因だろうと推測しました。


現在のPC環境では、ほとんど目立たないかもしれませんが、
モバイル環境だと、今のハイスペックデバイスでも、このメモリゴミ処理がそこそこ大きくなります。

ただ、通常のモバイルデバイスは、デフォルトで30fpsに固定され、
30fpsだと、そもそも滑らかさが低いので、通常のゲームなら気にする機会はほぼないでしょう。

しかし、60fpsを超えると、滑らかさが発生します。
この滑らかさゆえに、一瞬のゴミ処理が、際立つことになります。
また、30fpsの倍のスピードでゴミも発生することになるので、
その瞬間的なカクつき頻度も倍になります。


もちろん、
unityの仕様にのっとり、極力ガベージアロケードが発生しないような取り組みが前提ではありますが
それでも、unity内部のせいや、他のライブラリなどが原因でメモリゴミが発生することを回避するのはかなり困難だと思っています。

そして、数百バイト程度しかないゴミを、
Unityは、わざわざStop the worldして、処理してくれているようです。
60fps以上だと、その一瞬に、わずかに画面がカクッと止まるのが、
めちゃくちゃ目立ちます。


・対策


そこでUnity2019頃から誕生したのが、
 incremental GC
という機能のようです。


Player Settings 内の Configration内にその項目はあります。
各プラットフォームごとにチェックボタンが存在しており、
デフォルトはオフのようですが、バージョンやテンプレートによっては
最初からオンであることもあるようです。


その機能の内容は、ググると沢山でてきますが、
つまり、通常は一定ごとにまとめて行っているカベージ処理を、
まとめてではなく、常時少しずつ行うようにする、というもの。

ゴミ処理の分散化 

という意味のようです。


分散することで、全体の負荷はわずかに上昇してしまうようですが、
瞬間的なstop the worldへの抑制を期待できそうです。


というわけで、結局、
プロファイラーを血眼で睨みつづけて格闘しましたが、
どれだけやっても60fps下でのカベージアロケードによる瞬間的フリーズを
やっつけることができなかったので、

この incremental GC に頼ることになりました。
これは私の敗北です。

しかし、これをオンにすると、
stop the worldが消えたので、良しとすることにしました。



[Unity]動的メッシュ生成時のマテリアルが反映されない問題 & 動的生成メッシュへのテクスチャ方向問題

03-21,2024

今日は、
Unityで、コードから、動的にメッシュを生成し、ポリゴンを生成した際における
2つの問題についてぶちあたったので、書き留めておきます。


1つ目
◆動的メッシュ生成時のマテリアルが反映されない問題


mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.RecalculateNormals();

などによって、
独自にポリゴンメッシュを生成した場合、

そのオブジェクトに、
MeshRendererを、AddCompornentして、Materialを引き渡しても、
ちっとも反映されません。原因は不明です。
Inspectorで確認すると、マテリアルはちゃんと引き渡されていますが、
シーン上でも画面上でも透明になっていて、最初はメッシュ生成に失敗しているのかと
勘違いしてしまいます。
Inspector上でマテリアルを再設定してやると何故か反映されます。謎。


◇解決方法
オブジェクト自体は最初から用意しておき、
そのオブジェクトに、最初から空のMesh Filterを追加しておきます。
更に、マテリアルをセット済みのMesh Rendererを追加しておきます。

コードでは、その空のMesh Filterのインスタンスに対して、
動的にメッシュを生成し、
マテリアルは、既に追加しているマテリアルコンポーネントをGetConpornentして取得し、
更新するやり方でうまくいきます。



2つ目
◆動的生成メッシュへのテクスチャ方向問題


例えば、Y軸の高さが0の、平面ポリゴンメッシュを生成した場合、
そこにマテリアルでテクスチャやシェーダーを貼ると、UVの方向がうまく行かない場合があります。
おそらく、デフォルトのUV方向がZ軸方向になってたりして、生成した平面に対して間違っているせいかと思われます。
(動的生成メッシュ関係なく、UV方向によっては、普通のQuadポリゴンでもなるかも)

Mesh.setUVで、UV座標をいじっても解決できそうですが、
Shader Graphで、positionノードから特定軸だけとかをsplitして、それをテクスチャ等に繋ぐことで、UV方向を変えてやるのが簡単そうです。




blenderの入っていないunity for mac で、blenderからインポートしたオブジェクトは表示されない

11-21,2023


昨今のUnityでは、Blenderで作成した3Dモデルをインポートする際、
いちいちFBXファイルに変換せずとも、
直接Blendファイルをインポートできます。
とても便利です。

が、AndroidとiOS両方のアプリ開発をする上で、
つまづいたので、ここに記します。


私は基本的にはWindows上で開発をします。
BlenderもWindowsで使います。

そして、iOS用にビルドする際には、
Windowsで作成したデータを、
UnityのPlasticSCMを使って、MacのUnityへ送っています。


・・・ところが、
ここで奇妙な現象が発生しました。

iPhone実機で、3Dモデルが表示されていなかったのです。


最初は、実機ベースの現象かと思い、
ずいぶんと時間を無駄にしてしまいました。
数週間くらい解決できませんでした・・・。

実機ベースの問題ではないので、
実機ベースで考えても答えが見つからないのは当然なのです・・・おお神よ


また、私はAndroid端末を持っていないので、
Android端末では、そのモデルが表示されている、ということにも
ずっと気づかずにいました。

勝手に、iOSで表示されていないのだから、Androidでも表示されていないだろう
・・・と思い込んでいました。

しかし、今日、
たまたまAndroidユーザーの人がそのモデルの表示されている
スクショを投稿していたのを見て、
私は膝から崩れ落ちたのでした。


Androidでは表示されている・・・、
・・・そう、これは実機ベースの問題ではなく
iOSだけの問題、あるいは、iOSビルドを行うMac上の問題である!!!
・・・ということに、
私はこの時、初めて気づきました。


Mac上のunityで確認してみると、案の定表示されていませんでした。
Windows上で開発を行っていると、
Macへのデータ移行は流れ作業になり、
いちいち確認しなくなっていくものですが、
それがあだとなったようです。


そして、なぜ表示されていないのだろう・・・と思い、
該当のモデルをMacのunityで確認すると、
そのモデルデータ(Blendファイル)が、Unknowファイルになっていました。

Unity for macが、なんのファイルか特定できないため、
そのファイルはmissingファイル扱いにされており、
そのMacでビルドしたiOSでは、モデルが表示されていない
・・・ということなのでした。


特定できない理由は、
そのMacに、Blenderがインストールされていないことが原因のようです。

Macに使いもしないBlenderをインストールするのは面倒だったので、
最終的には、
Windows側で、BlendファイルをFBXに変換し、
ベースとなっているプレファブの中身を、
Blendファイルから、FBX入りのオブジェクトに変更することで
対応しました。

結局、Blenderから直接インポートできる~らくちん~
・・・の代償が、ここに表れていたという話でした。


ちなみに、今回は
blenderモデル → バリアントプレファブ化(a)し

その(a)の集合体 → プレファブ化(A)
したものを使っていたので、

(a)をFBXに変更できれば、一括で対応できますが、
これが少し難しかったので、併記しておきます。


バリアントプレファブ(a)をopenすると、
当然、「Blenderモデルをベースとする」と書かれており、
そのまま変更はできません。

そこで、
バリアントプレファブ(a)をopenした状態で、
バリアントプレファブ(a)のルートオブジェクトをunpackし、

そのルートオブジェクトに追加されているMeshなどを全て削除。

そしてその子オブジェクトに、
FBXを入れてやることで解決しました。
(FBXを入れると、スケールが1/100とかに違っていたりするので
 ちっちゃくて見えなくて表示されてない!!! と勘違いするので
 ここも要注意です)

ちなみに、その集合体(A)は、
実行時combine mesh化しますが、
combine mesh化する時は、
Blendファイルだろうが、FBXだろうが、
モデルのRead/WriteをONにしてあげないと、
Combine meshできないのでそのことも記しておきます。


今回も、同様ケースを検索しても、ぜんぜん引っかからないので
ここに記します。

google play consoleで、aabファイルがアップロードできない

11-07,2023


ある日突然、Google play consoleで、
aabファイルがアップロードできなくなりました。


いつものようにAndroidアプリの新しいリリースを行うため、
aabファイルをアップロードしようとすると・・・


"アップロードできませんでした。もう一度お試しください。"


というエラーが。

この文言以外のエラーメッセージがないのが、不気味です。


通常なら、ここでエラーが発生する場合は、
エラーの原因となっている箇所やポイントも一緒に表示されます。

例えば、バンドル番号が既にあります、とか、
そのターゲットAPIは使えませんとか、
認証キーが違いますかとか、などなど・・・

しかし、そういった追記が一切ないケース。
これは初めてでした。


とりあえず日本語で検索してみましたが、
見つかるのは、それ以外のエラーの対処方法ばかり。


次に英語で検索してみます。

すると、いくつかヒットしました。
2020年頃から現在まで、すこしずつ報告があるようです。

対処方法としては、
・キャッシュやクッキーを消す
・ブラウザを変える
・シークレットブラウザでアップしてみる
・PCを変える
・unityのverを変える

などなどが挙げられていました。

要は、ブラウザに問題があるみたいな推測のようです。


というわけで、全部やりました。
全部うまくいきませんでした。


そこで、他のプロジェクトのアプリでもやってみました。
すると、うまくいく時とうまくいかない時がありました。
・・・・どういうこと?


更に、検索を続けることに。

そんな中、
2日前にも、同様の問題で困っている海外の人の
google play consoleのフォーラムへの報告記事を発見!


すると、その人は、
chromeの開発ツールのログから、
アップロード時に、CORSエラーが多発していることを報告していました。

更に、何度もアップロードすると、
たまーーにうまく行くという内容
これにはびっくり!

しかも、aabファイルだけではなく、csvファイルのアップロード時にも
同様のエラーが出るとのこと。


一応google側のモデレーターのような人の返答がありましたが、
その内容は、上で触れたキャッシュを消すなどの対処方法のみ。


試しに10回くらい試してみました。
するとどうでしょう。
1回だけアップロードに成功・・・・!!

は!??


ということは、aabファイル側の問題ではないということになります。

でも、他PCからのアップロードすら、
失敗続きなので、
どういうことなのか意味がわかりません。

このプロジェクトだけで、エラーが多発するような感じでしょうか。


その後、20回くらい同じファイルをアップロードしてみましたが、
それらは全て失敗・・・・。



晩御飯を食べてから深夜1時くらいまで奮闘しましたが、
万策尽き、
わたしも結局、google play console のお問合せフォーラムに書きこむことに・・・
google側がまともな回答をしてくれないことは分かっていますが・・・


そんな状態でお布団に入ったせいか、
悪夢にうなされ深夜に目覚めるはめに・・・


そして翌朝、
起きてすぐ、もう一度トライ・・・。


・・・すると、

一発でアップロード成功しました。


は・・・・・!?



というわけで、結論

googleのサーバーの問題。


どうせ重くなってるとか、そういうやつでしょう・・・


個人的に、
アプリ開発で直面する深刻な問題って、
こういうのが一番多い・・・・


"aab"
"アップロードできませんでした。もう一度お試しください。"
"couldn't upload. try again."
"CORS"

とかの日本語で完全一致検索しても、出てこなかったので、
この記事が、同様ケースのgoogleに苦しめられる人々の助力になれば。

【2023】第二章・A戦争について語る時がきた

11-05,2023

syaou1.jpg

今日は、
A戦争のオンライン対戦をやっていて、
個人的に、最も面白い瞬間を書きます。


ちなみに、↑のキャラは
A戦争の小友です。

A戦争には、キャラクターの名前を関した武器が登場するのですが、
その中でも、
『Syao-U』
という名前の、サブマシンガンがあるのです。

サブマシンガンの中では、最も射撃間隔が高レートの、とても強い武器です。


A戦争のオンライン対戦で勝利すると、
1Gathaポイントを入手でき、それを使ってガチャを回すと、
ランダムで、Call Picと呼ばれる壁紙が手に入ります。

↑の絵は、その Call Pic の中の1枚です。


では、私が個人的に思う面白い瞬間を、
下に3つ書きました。


面白い瞬間その1

・スナイパーで狙われる


A戦争にも、他のFPS同様、スナイパーライフルがあります。
ただし、A戦争は見降ろし型の2Dなので、
扱いが難しくはありますが、

通常の銃の場合は、画面範囲内が視界になるのに対し、
スナイパーライフルなら、
死角を除く範囲内で、視線をどこまでも延長できるという特性があり、
これが、通常の銃のプレイヤーに対して、かなりのアドバンテージになります。

通常のプレイヤーからすれば、画面外から撃たれてしまい、
反撃がかなり困難になってしまいます。
更に、屋上等から射撃されると、通常の戦法では、反撃はほぼ不可能になります。

更に、裏取りルートなどが存在しない一方通行の屋上から狙われてしまうと、
その状況を打破すること自体、ほぼ不可能になったりもします。

なので、
私はスナイパーで狙われると、
八方ふさがりのような状況が発生するので、
むちゃくちゃ面白くなります。


ただ、残念なことに、
現在の限られたプレイヤーの中でも、スナイパーをやる人はほとんどいません。
最近ではyapuuさんとstoneさんくらいで、
それ以外の人がスナイパーをやってるのを見るのは稀です。

スナイパーは、基本的にその場にとどまることになるため、
A戦争のドミネーションベースのルール上では、
スナイパーをやること自体が、勝敗において不利になってしまいやすいことが
原因かもしれませんが、
立地や戦況によっては、神の如く強くなるため、
もっとスナイパーが増えるといいなと私は思っています。



面白い瞬間その2

・多勢に無勢


A戦争は、前回の記事でも触れたように、
現在まで長らくプレイヤーが激減壊滅絶滅危惧種状態です。

ちなみに昨日の土曜は、
5人しか集まりませんでした・・・・

しかも、5人がずっといるわけではありません。


そんな感じなので、
頻繁に、
2 vs 1 や  3 vs 2 と言った、多勢に無勢状態が生まれます。

そしてこの数は、人数が少ないほど、その戦力格差が割合的に顕著になるため、
2 vs 1の時は、
1人チームの視点では、
単純に、2倍の戦力のチームを相手にしなければならなくなります。

これがFPSでよくあるデスマッチルールなら、
うまい人が独走することもできますが、
ドミネーションのような陣地戦となると、全く景色は変わります。

更に言えば、
A戦争の現在のAttack & Deffendルールでは、
防衛側の方が不利なので、
2 vs 1 の状態で、自分が1人側 & 防衛側 だった時、
その難易度は最高に達します。

こうした時が、私はむちゃくちゃ面白いです。


とは言え、基本的には6 vs 6などの、
大勢で戦う方が面白いのですが、
最近はもっぱら少人数なので、
そんな中でよくおこる 2 vs 1 の状況を選抜しました。



面白い瞬間その3

・猛烈な攻撃


AC-130やサイオンバードが延々と空を覆い、
地上ではタンクからの砲撃の嵐と、
無数のセントリーからの銃弾で埋め尽くされ、
どうしようもない状況。


ひと昔前のAkaicシステム時代には、
そういうことが時折発生していました。

Akaicシステムでは、低Legend Starの人ほど、
マジックが貯まりやすいという仕様があったので、
AC-130などをセットしておけば、
低Legend Starの人なら簡単にそれを出せるという状況がありました。

しかし残念ながら、
今では、そのような状況が起こることはまずありません。

たまに、支援物質から出てきたAC-130などが発生するくらいでしょうか。

しかし、1機出たくらいでは、現在のルール上においては、
戦況にあまり影響がないという感じです。
特に、現状のような少人数下では、
AC-130などを操作している間は、
特定の拠点の防衛や確保が返っておろそかになるため、
使うと負けやすい、ということさえおきてしまうことがあるのでした。


ともあれ、爆撃が延々と連続する地獄のような状況はとても面白いので、
今のルールでも、人が多くなって、また味わう機会があればいいなと思っています。



最後に
現在のA戦争での、面白いMAPを書きます。

それは、
・MAPユグドラシル
・MAPコロシアム
・MAPデュエル
・MAPぐるんぱ

です。

これらのMAPに共通するのは、
一方的な攻撃になりやすい高低差がある所です。

特に、ユグドラシルなどでは、
一番上から機関銃やスナイパーなどで攻撃されると、
一番下からスタートするプレーヤーは、
上にある拠点に到達すらできずに終わります。

こういうMAPでは、
一方的な一方試合になりやすいです。


そういう時の、
下から、死にながら這いずって、這いずって・・・それなのに打ち殺され、
もうどうすることもできない・・・・
という完全理不尽不可能状態が、
私はとても大好きで面白いです。



・・・というわけで、
私は、A戦争の2つ目の記事を書きました。

ゲームA戦争のダウンロードはこちら
https://andymente.moo.jp/html/game2/a-war/


毎週土曜14:00~18:00や
祝日などの昼間に、
Sanctuaryにてお待ちしております。
何もわからない初心者でも、何もわからない人でも、誰でも大歓迎でございます。