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)來表示旋轉。旋轉的差異可能是由於以下原因之一導致的:
- 歐拉角(Euler angles)轉換為四元數的過程中可能存在精度損失。歐拉角存在萬向鎖問題和旋轉順序問題,這可能導致從歐拉角轉換為四元數時出現不準確的結果。
- 根節點旋轉的計算可能受到其他因素的影響,例如動畫過程中的插值算法、關鍵幀的設置、平滑過渡等。這些因素可能會導致計算結果與期望的差異。
感謝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 DevelopersAhead-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