91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

[Unity 3D] Unity 3D 性能優化(二)

發布時間:2020-07-11 20:12:58 來源:網絡 閱讀:199 作者:蓬萊仙羽 欄目:開發技術

IsAlive

U3D的粒子系統腳本接口相信很多人都用過,ParticleSyetem類的一系列接口都有一個bool類型的參數——withChildren,通過這個參數可以直接將相同的判斷或者操作應用到一整個通過Transform父子關系樹關聯起來的ParticleSystem實例集合上。然而,但凡方便的功能,里面就必然有性能陷阱……

以IsAlive這個接口為例(用來判斷粒子系統是否所有粒子都已經消亡,一般用在非loop的例子發射器上),看看U3D里是如何實現這個接口的:

[csharp] view plaincopy
  1. public bool IsAlive()  
  2. {  
  3.     bool withChildren = true;  
  4.     return this.IsAlive(withChildren);  
  5. }  
[csharp] view plaincopy
  1. public bool IsAlive(bool withChildren)  
  2. {  
  3.     if (withChildren)  
  4.     {  
  5.         ParticleSystem[] particleSystems = ParticleSystem.GetParticleSystems(this);  
  6.         ParticleSystem[] array = particleSystems;  
  7.         for (int i = 0; i < array.Length; i++)  
  8.         {  
  9.             ParticleSystem particleSystem = array[i];  
  10.             if (particleSystem.Internal_IsAlive())  
  11.             {  
  12.                 return true;  
  13.             }  
  14.         }  
  15.         return false;  
  16.     }  
  17.     return this.Internal_IsAlive();  
  18. }  

可以看到,如果傳遞的withChildren參數為true,那么函數會先嘗試調用GetParticleSystems(this)來獲取包括下級gameObject在內的所有能找得到的粒子系統組件,然后對這些粒子系統組件依次再調用IsAlive判斷。而如果withChildren為false,就僅僅會判斷自身。那么自然,開銷大小與否,關鍵就在GetParticleSystems的實現上了。

[csharp] view plaincopy
  1. internal static ParticleSystem[] GetParticleSystems(ParticleSystem root)  
  2. {  
  3.     if (!root)  
  4.     {  
  5.         return null;  
  6.     }  
  7.     List<ParticleSystem> list = new List<ParticleSystem>();  
  8.     list.Add(root);  
  9.     ParticleSystem.GetDirectParticleSystemChildrenRecursive(root.transform, list);  
  10.     return list.ToArray();  
  11. }  
[csharp] view plaincopy
  1. private static void GetDirectParticleSystemChildrenRecursive(Transform transform, List<ParticleSystem> particleSystems)  
  2. {  
  3.     foreach (Transform transform2 in transform)  
  4.     {  
  5.         ParticleSystem component = transform2.gameObject.GetComponent<ParticleSystem>();  
  6.         if (component != null)  
  7.         {  
  8.             particleSystems.Add(component);  
  9.             ParticleSystem.GetDirectParticleSystemChildrenRecursive(transform2, particleSystems);  
  10.         }  
  11.     }  
  12. }  

U3D對獲取所有下級gameObject實例上的粒子系統組件使用了遞歸的方式,并在遞歸結束后返回結果列表時做了一次列表元素復制(List.ToArray()),并且在獲取粒子系統組件的時候用的是transform2.gameObject.GetComponent<ParticleSystem>(),而不是transform2.GetComponent<ParticleSystem>(),從上一篇文章里我們已經用實驗證實了,前一種方式開銷更大。看到這里,我們心里大概已經有譜了,那就是——效率絕對不會高到哪里去,影響性能的地方太多了……還是設計一個小實驗來看看這種情況下應該用什么樣的方式更好吧:

設計實驗——一個兩層結構,一個父gameObject掛載一個ParticleSystem組件,兩個子gameObject分別掛載一個PariticleSystem組件,采用兩種不同的方式對這個組合判斷IsAlive各8×1024×1024次。
方案一,直接對父gameObject上的PariticleSystem調用IsAlive(true);
方案二,在循環前,先用GetComponentsInChildren將所有的PariticleSystem存入一個List,循環中對這個List做遍歷,對List里每一個ParticleSystem調用IsAlive(false);
實驗結果——方案一約3900ms,方案二約65ms。

結果對比很明顯。其實,U3D提供的這個接口的意義在于,當不是需要進行那么頻繁的調用時,可以用IsAlive(true)來省掉手動獲取所有子粒子系統的過程,讓代碼簡潔一些,雖然U3D目前對這個接口的實現有的地方還值得斟酌。ParticleSystem提供的這一族接口(IsAlive只是其中之一,此外還有Play,Pause,Stop等等),如果使用頻率不是很高,比如僅僅是初始化或者銷毀的時候做一次性調用,那么即便是withChildren參數是true也沒有什么大不了的,還能少些很多代碼,何樂而不為;但如果需要頻繁調用,比如每幀都對粒子系統集合判斷IsAlive,這種情況下,一定不能懶惰,該寫的東西還是要寫的。另外值得注意的一點,IsAlive這一族接口的無參形式,是默認withChildren為true的,使用的時候可別搞錯了。

PS,留意一下GetDirectParticleSystemRecursive的實現方式,你會發現它有一個遞歸條件,就是節點上必須要有PariticleSystem組件,在遞歸過程中,一旦發現某個節點上沒有ParticleSystem組件時,父子關系樹上的這一枝就算遍歷到頭了,再往下即便是還有ParticleSystem存在也會被忽略。因此,如果你面對的ParticleSystem集合就恰好存在這樣的斷層,那最好還是自己勤快一點,自己動手用GetComonentsInChildren來查找所有的粒子系統組件。
向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

un %d
AI

安吉县| 乐安县| 四会市| 东丰县| 福贡县| 锦州市| 莱阳市| 海宁市| 敖汉旗| 浮山县| 稻城县| 黄石市| 济阳县| 兴海县| 连平县| 商洛市| 海丰县| 芒康县| 定襄县| 武鸣县| 洱源县| 嘉荫县| 泸州市| 湟中县| 巴马| 社会| 巴林右旗| 海伦市| 连江县| 庆云县| 柳州市| 上饶县| 中阳县| 万山特区| 伊宁市| 天峨县| 南和县| 福泉市| 巴东县| 榆社县| 隆昌县|