博客 / 詳情

返回

關於Addressable打包圖集與圖片都打進去造成冗餘

1)關於Addressable打包圖集與圖片都打進去造成冗餘
​2)Unity如何計算Root動畫旋轉
3)IL2CPP編譯的Protobuf反射類運行時報空
4)為什麼Active Constraints會出現過高的現象


這是第337篇UWA技術知識分享的推送,精選了UWA社區的熱門話題,涵蓋了UWA問答、社區帖子等技術知識點,助力大家更全面地掌握和學習。

UWA社區主頁:community.uwa4d.com
UWA QQ羣:465082844

Addressable

Q:關於Addressable打包圖集與圖片都打進去造成冗餘。

Unity版本:2021.2.13f1c1
Addressable版本:1.19.16(cn版本)

使用的是Addressable的默認Group,場景中只使用了decal3的UI圖片,但是打包最後的資源,Addressable的包中包含了兩個資源,正常應該只有圖集資源才對(如下圖)。

另外,看了Addressable打包流程的代碼,Unity把關聯的圖片加入依賴打包列表,但是又在之後對圖片檢測做了生成圖集的處理。原生打包不會對圖集裏的圖片再做處理嗎?

A:可以切換com.unity.ScriptableBuildPipeline版本到1.21.5試試看,1.21.5修復的問題應該包括這個。
更新日誌:
https://docs.unity3d.com/Packages/com.unity.scriptablebuildpi...

感謝liuxianfeng@UWA問答社區提供了回答

Animation

Q:想了解Unity的RootMotion的實現細節,請問Unity是怎麼計算Root動畫旋轉的?

一個動畫,如果配置正確,AnimationClip裏會多兩段曲線數據,RootT、RootQ分別是根節點的位移和旋轉信息。但是當我用Animator跑起來後,我們每幀RootMotion旋轉多少,Root節點逆向旋轉多少,是怎麼計算出來的呢?

樸素的想法是:旋轉當前幀的RootQ相對於第0幀RootQ的旋轉的eulerAngles.y。但是經過我多次測試,並不是這個值,而是有偏差的一個值。有時候多幾度,有時候少幾度。

沒有Unity源碼的情況下,很難知道它的計算方法。我去看了Godot,其方法是正常把當前旋轉和第0幀做差值。

比如這個動畫,我已經把數據刪得差不多了。第1幀,Animator認為應該轉24.068,這兩個旋轉的歐拉角表示分別是(277.77, 66.96, 81.36) 、(279.53, 74.28, 100.03),from to旋轉的歐拉角是(3.29, 25.78, 0.02) 。這個25.78和24差得不多,但是總歸不一樣。其他測試數據類似,都是差一點。

A:對於旋轉的計算,Unity使用了四元數(Quaternions)來表示旋轉。旋轉的差異可能是由於以下原因之一導致的:

  1. 歐拉角(Euler angles)轉換為四元數的過程中可能存在精度損失。歐拉角存在萬向鎖問題和旋轉順序問題,這可能導致從歐拉角轉換為四元數時出現不準確的結果。
  2. 根節點旋轉的計算可能受到其他因素的影響,例如動畫過程中的插值算法、關鍵幀的設置、平滑過渡等。這些因素可能會導致計算結果與期望的差異。

感謝NG週@UWA問答社區提供了回答

Script

Q:IL2CPP編譯的Protobuf反射類運行時報空,問題發生時,會閃崩,閃崩日誌信息:
ErrorNotNull:"c# exception:System.TypeInitializationException: The type initializer for 'abcConfigReflection' threw an exception. ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ExecutionEngineException: Attempting to call method 'Google.Protobuf.Reflection.ReflectionUtil+ReflectionHelper`2[[System.IntPtr&, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]::.ctor' for which no ahead of time (AOT) code was generated.n

at System.Reflection.MonoCMethod.InternalInvoke (System.Object obj, System.Object[] parameters) [0x00000] in <00000000000000000000000000000000>:0 n

at System.Activator.CreateInstance (System.Type type, System.Boolean nonPublic) [0x00000] in <00000000000000000000000000000000>:0 n

at Google.Protobuf.Reflection.ReflectionUtil.GetReflectionHelper (System.Type t1, System.Type t2) [0x00000] in <00000000000000000000000000000000>:0 n

at Google.Protobuf.Reflection.ReflectionUtil.CreateFuncIMessageObject (System.Reflection.MethodInfo method) [0x00000] in <00000000000000000000000000000000>:0 n
...
具體信息請見原網頁。

看下來是因為AOT編譯時代碼剔除所致,問題非常偶現。我們的QA基本上沒有跑出來過這個問題,但是放到外網就有一堆玩家遇到此問題,蹊蹺的是哪怕同一個手機也是偶然才報。

Proto Github項目有人提過:
https://github.com/protocolbuffers/protobuf/issues/5422

這個問題包括下面回覆主要提了兩點:
1. linker包含Google.Protobuf程序集
2. AOT編譯器不會為T、為AnyEnum的泛型方法,針對枚舉參數泛型方法創建顯式調用類https://docs.unity3d.com/cn/current/Manual/ScriptingRestricti...

和我這個問題不同點是,abcConfigReflection是一個類,不是枚舉,而且整個項目這個類會有很多。

我用的Proto版本3.6.1,而且Proto也在3.6.0版本説修改了> AOT generics issues in Unity/il2cpp have a workaround (see commit 1b219a1 for details)。

Protobuf源碼確實加了強制反射的代碼:

static FileDescriptor()

        {
            ForceReflectionInitialization<Syntax>();
            ForceReflectionInitialization<NullValue>();
            ForceReflectionInitialization<Field.Types.Cardinality>();
            ForceReflectionInitialization<Field.Types.Kind>();
            ForceReflectionInitialization<Value.KindOneofCase>();
        }

當然我有加Google.Protobuf程序集到linker,還是不能解決。後來我加了Assembly-CSharp程序集到linker,也就是整個自定義代碼全部不剔除,目前因為不方便放外網,也不清楚有沒有解決這個問題。

使用Protobuf序列化數據應該是常規操作,相信應該有很多人遇到,不知道大家處理方案是什麼?

A:可以嘗試以下方法:
Initialize the library and verify operation | Android Developers

Ahead-of-time compile (AOT)
Ahead-of-time compile is required for the IL2CPP backend and Unity versions 2017 and 2018 (but not for later versions of Unity).<br/>
The AOT compiler may not generate code for generic methods. You need to force the compiler to generate the proper code required for protobuf by adding the following method:<br/>

using Google.Protobuf.Reflection;
using UnityEngine.Scripting;

...

// Don't call this method.
[Preserve]
void ExampleOfForceReflectionInitializationForProtobuf()
{
    FileDescriptor.ForceReflectionInitialization<Scene>();
    FileDescriptor.ForceReflectionInitialization<ShadowType>();
    FileDescriptor.ForceReflectionInitialization<LevelType>();
    ...
    // Add FileDescriptor.ForceReflectionInitialization<T> for each generated enum.
    // You can find the list of enums in DevTuningfork.cs -> enum section
    // or in the list of enums in Google -> Android Performance Tuner.
}

感謝hanxu@UWA問答社區提供了回答

Physics

Q:通過Profiler分析項目,發現其中Active Constraints這一項會突然出現一個很不合理的峯值。目前只發現與角色身上是否掛載剛體有關。

但是與剛體數量對比起來,這種極高的Active Constraints為何會發生是毫無頭緒的。在此向各位請教下。

A:從官方文檔的截圖裏可以看到,在一個剛體的情況下,官方的實例裏依舊也會產生17.29KB的Active Constraints。估計是統計方式有問題,又或者是理解上存在差異。

我在Unity 2018和Unity 2020這兩個版本都見到過Active Constraints過高的現象。

至少目前來講,這個數量級的Active Constraints還屬於可接受範圍(官方自己都覺得沒問題),不需要去專門花費大量時間去排查優化。

感謝題主午休達人@UWA問答社區提供了回答

封面圖來源於網絡


今天的分享就到這裏。生有涯而知無涯,在漫漫的開發週期中,我們遇到的問題只是冰山一角,UWA社區願伴你同行,一起探索分享。歡迎更多的開發者加入UWA社區。

UWA官網:www.uwa4d.com
UWA社區:community.uwa4d.com
UWA學堂:edu.uwa4d.com
官方技術QQ羣:465082844

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.