Luaグローバル変数コードの仕様

今回の話題:

1)Luaグローバル変数コードの仕様

2)AssetBundleLockPersistentManagerのコスト

3)Unityの内蔵フォントは、アセット検出レポートでは冗長アセットとは見なされない

4)特定のAndroidデバイスでAdrenoがフリーズする

5)MaskとRectMaskのパフォーマンスの違い


 

Lua

 

Q:スクリプト支援開発としてLua言語を使用することは非常に人気がありますが、Lua言語のグローバル変数は面倒なことでもあります。宣言なしで使用でき、コンパイラーは名前の変更や上書きのエラーを報告しないため、少し油断したらグローバル変数上書きされてBugが発生し、さらにGameObjectを参照するグローバル変数がリークを引き起こす可能性があります。

 

開発プロセスで、Luaグローバル変数のコード仕様を作成しますか?例:グローバル変数はいつ使用できますか?宣言する方法は?上書きやその他の問題を回避する方法は?

 

A:Lua仮想マシンの起動後、適切なタイミングでluaGlobalCheck.luaファイルを実行できます。このファイルは_Gのメタテーブルおよびメタメソッドを設定します。_newindexおよび_indexメタメソッドをオーバーライドすることにより、グローバル変数の作成と存在しないグローバル変数にアクセス時にエラの提示を禁止します。このようにして、グローバル変数の随意な作成と上書き問題が避けられます。

setmetatable(_G, 
{
    -- グローバル変数の作成を禁止
    __newindex = function(_, k)
        error("attempt to add a new value to global,key: " .. k, 2)
    end,

    -- グローバル変数のアクセスを禁止
    __index = function(_, k)
        error("attempt to index a global value,key: "..k,2)
    end
})

 

AssetBundle

 

Q:パフォーマンス曲線を見ると、あるフレームAssetBundleがロードされると、LockPersistentManagerに多くの時間がかかることがわかります。これは最適化できますか?

 

A1:これは、現在のフレームまたは前のフレームでLoadAsyncを介して大量のアセットがロードされていることを意味します。本質的には、ロードされたアセットが大きすぎるということです。独自のアセットを適切に最適化すると、Loading.LockPersistentManagerのコストを削減できます。さらに、非同期ロードを同期ロードに置き換えることにより、LockPersistentManagerは表示されませんが、合計ロードが変更されていないため、合計ロード時間は変更されません。

 

A2:Unity 2019.4.1バージョンでは、bundle.LoadFromFileAsyncは実際にはメインスレッドのIntegrate Assetで実行され、PreloadManagerスレッドのLoadAssetAsyncは同時に実行できないため、ロックする必要があります。そして、LockPersistentmanagerが表示されます。片側が終了するまでロックされます。

本質は、実装が完全ではないということです。Spin Lockを使用して、Application.backgroundLoadingPriorityで片側が終了するまでロックされル必要はなく、指定された時間までロックしてから、次のフレームに移動できます。

Unity 2019.4.11および2019.4.16は、メインスレッドがBundleを読み取ってロックを待機する問題を修正しました。

 

Unity 2020.1.17を使用してiOSでテストしたところ、基本的に解決されました。

ただし、メインスレッドを非同期でロードしロックを待機する現象もいくつかあります。恐らくアセットが大きすぎ、コレクションの依存関係の時間が長すぎてトリガーられたと推定します。

 

AssetBundle

 

Q:私たちのプロジェクトでは、2つのインターフェイスのPrefabはUnity独自のArialフォントで生成されたBundleですが、アセット検出にアップロードして、レポートで内蔵のフォントが冗長アセットであることが見えませんでした

 

A1:このArialはUnityの内蔵アセットに属しています。APKをパッケージ化すると、unity default resourcesに入力されました。そして、AssetBundleで使用されたArialフォントは参照関係で、対応するAssetBundleにパッケージ化されません。したがって、冗長アセットが見られないのは正常です。

AssetStudioを使用して、APKパッケージのassets / bin / Data /ディレクトリにあるunity default resourcesを開くと、表示できるようになりました。

 

A2:Arialフォントの使用はお勧めしません。一部のローエンドコンピュータでは中国語を表示できません。主な理由は、モデルによってデフォルトのフォントが異なるためです。

 

Rendering

Q:特定のAndroidデバイスで、Adrenoに画面のフリーズ(GPUハング)の問題があります。

 

この現象は、画面がフリーズして更新されないということですが、音楽UIをクリックしたときの効果音は引き続き再生できます。 Unity Profilerを使用してCPUを確認しても、例外やフラッシュバックはありません。画面がフリーズしたときにキャッチされたエラーログは、元の質問と回答をクリックして表示できます。

 

A1:MonoパッケージがXiaomiデバイスでも同じ状況が発生しましたが、IL2CPPに変更した後は再発しませんでした。

 

A2:A1の方法は確かに一部のモデルで効果的ですが、一部のMTKデバイスでも同様の問題が発生します。Unityバッチ処理、動的バッチ処理、またはGPUインスタンスの問題のように感じます。単一のバッチでGPU Instanceの数を減らしたら、少しよくなります。デバイスのGPUにマッチする数をしてください。

 

A3:Unityが公式に提供しているGPU Instanceソリューションを使用して実装されています。

https://github.com/Unity-Technologies/Animation-Instancing

このスキームのデフォルトのShaderは、戦闘ユニットのレンダリングに使用され、奇妙なフラッシュバックとクラッシュが発生しました。デフォルトのShaderは次のとおりです。

このShaderのloadMatFromTexture関数は9回呼び出され、loadMatFromTextureの実装は次のとおりです。

ここでの問題は、サンプリング時間が長すぎることが原因である可能性があり、修正後に現在のフレームが使用され、Lerp操作は実行されず、各頂点は2つのボーンによってのみ制御され、テストしたらクラッシュしなかったことが確認できます。エフェクトロスの許容レベルについてはまだアーティストに確認されています。後のコードは次のようになります。

 

UGUI

 

Q:Unity UIのMaskとRectMaskのパフォーマンスに違いはありますか?

 

A1:RectMask2D:Imageコンポーネントに依存する必要はなく、そのクリッピング領域はRectTransformのrectサイズです。

プロパティ1:RectMask2Dノードの下のすべての子ノードと外部UIノードはバッチ処理したり、複数のRectMask2D間にバッチ処理したりすることはできません。

プロパティ2:Depthを計算する場合、すべてのRectMask2Dは一般的なUIノードとして扱われますが、CanvasRendererコンポーネントがなく、UIコントロールのbottomUIと見なすことはできません。

Mask:コンポーネントはImageコンポーネントに依存する必要があり、クリッピング領域はImageのサイズです。

プロパティ1:Maskには最初と最後にさらに2つのDraw Callがあり(最初の= Maskノード、最後= Maskノードの下の子ノードがトラバースした後)、複数のMaskがバッチ条件を満たしている場合、これらの2つのDraw Callに対応的にバッチ処理できます(Mask1のヘッドとMask2のヘッドが結合されます。Mask1のテールとMask2のテールが結合され、ヘッドとテールを結合することはできません。)

プロパティ2:Depthを計算するとき、Maskのヘッドにトラバースするときは、バッチ処理できないUIノードとして扱いますが、子UIノードとして使用できるbottomUIに注意してください。

プロパティ3:Mask内のUIノードとマスク外のUIノードを一緒にバッチ処理することはできませんが、バッチ条件を満たしている場合は、複数のマスク内のUIノードを一緒にバッチ処理できます。

マスク3のプロパティから、Maskをまとめてバッチ処理できるため、Maskが多いほど悪いというわけではないことがわかります。次のように結論付けられました:

インターフェイスにMaskが1つしかない場合、RectMask2DはMaskよりも優れています。

2つのMaskがある場合、2つは類似しています。

マスクが3つ以上ある場合、MaskはRectMask2Dよりも優れています。

 

 

A2:複数のMaskのバッチからA2の結論を検討することができます。追加は次のとおりです。Mask でStencilを書き込むと追加のOverDrawがあり、Mask2DにはOverDrawはありませんが、各ItemはMaskRectと比較する必要があるから、一定的なCPUコストが発生します(Maskは多くのItemに適しており、Mask2Dは少数のItemに推奨されます)。

 

A3:UIバッチ処理の観点から、同じレベルで:

Maskは優先度の高い特殊なコンポーネントであり、優先的に実行します。Maskはそれ自体とUIのMaterialを変更します。両者は異なります。

RectMask2Dは特別な権限のないクリッパーであり、そのバッチ処理ルールは他の通常のコンポーネントと同じです。 RectMask2Dは、UIのClipRectを変更します。したがって、同じRectMask2Dの下にないUIコンポーネントを一緒にバッチ処理することはできません。

UIをバッチ処理できるかどうかの理由として、次のように推測します。

Different Rect Clippingとは、RectMask2Dから通常のコンポーネントへの切り替えを指します。Different Clip Rectとは、2つのRectMask2D間の切り替えを指します。


UWA公式サイト:https://jp.uwa4d.com

UWA公式ブログ:https://blog.jp.uwa4d.com

UWA公式Q&Aコミュニティ(中国語注意):https://answer.uwa4d.com