您好,登錄后才能下訂單哦!
今天小編給大家分享一下Unity代碼層優化和規避的方法有哪些的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
1.盡可能少用不用循環邏輯精簡循環主體代碼(While,for,foreach,遞歸)
在業務需求層面能避免循環邏輯的時候盡量避免,確實是需要循環邏輯的話就把邏輯理清楚,主要循環體的代碼不能有任何多余的變量或者多余內存占用。另外:
for(int i=0;i<myArray.Length;i++)//避免 int length=myArray.Length; for(int i=0;i<length;i++) //提倡
2.巧用生命周期函數Update和LateUpdata。
明確每一幀Updata和固定幀LateUpdata的函數意義,在使用兩者的時候要明確當前需求是否要高頻率的執行調用,如果確實需要每一幀都執行調用或者在單幀上進行邏輯處理(比如畫面渲染等)那我們就用到Updata;另外如果我們對刷新執行的頻率要求不高(比如物理的位移旋轉等邏輯)我們就可以用到LateUpdata;刪除空的Update方法
void Update() { if (isTrue) { isTrue = false;}//一定要加條件保護 } private void LateUpdate() { transform.Rotate(Vector3.up * Time.fixedDeltaTime * speed); }
3.只在變化發生時才去執行代碼(UI界面數據刷新)。
很多時候的邏輯我們都是不用特殊處理時時關照的,比如UI界面的數據刷新,很多初學者喜歡把ui的刷新邏輯直接扔在Updata里面,這樣雖然很省事我們不必再單獨的對界面數據的管理和維護,但是界面如果數據量大,更新頻繁這時候對程序就造成很大的渲染負擔,我們可以通過使用委托等方法只有在有數據更新的時候調用ui的界面刷新邏輯
public delegate void MyDelegate(int score);//定義委托 public MyDelegate myDelegate; //聲明委托 private int score = 0; public int Score { get => score; set { score = value; myDelegate?.Invoke(score); } } private void Start() { myDelegate += UpdataUIData;//委托注冊事件 } public void UpdataUIData(int score) { //刷新ui界面數據 }
4.將需要頻繁執行且不能通過事件觸發的方法改為每隔幾幀執行一次。比如剛才說的lateUpdata固定幀。除去這個外我們還可以靈活運用協同,在一開始的時候就開啟一個協同
private void Start() { InvokeRepeating("RunSomeThing",1,5);//一秒鐘執行五次 } private int interval = 3;//間隔幀 void Update() { if (Time.frameCount % interval == 0)//每三幀執行一次 { RunSomeThing(); } } public void RunSomeThing() { }
5.使用緩存存儲需要反復獲取和使用的值。
.動態獲取的組件可以存儲到全局變量中,使用的時候直接取避免了反復獲取
.反復使用的臨時變量,聲明的時候我們就可以放到全局存儲起來
.動態實例化出來的對象,我們要想辦法給管理起來方便下次直接使用
6.數值類型盡量避免使用float,而使用int,特別是在手機游戲中,盡量少用復雜的數學函數,比如sin,cos等函數。改除法/為乘法,例如:使用x*0.5f而不是 x/2.0f 。
7.主動進行垃圾回收
void Update() { //固定時間GC回收但也不能太頻繁,建議跳轉場景的時候或者重要模塊切換的時候回收 if (Time.frameCount % 50 == 0) { GC.Collect(); } }
1. SendMessage()和BroadcastMessage()使用了反射而反射會造成更多的CPU開銷。你可以直接調用或通過C#的委托來實現。
2. Find()方法會遍歷內存中的每個GameObject和組件,隨著項目規模的擴張,它的開銷將會越來越大。避免使用Find()和與其類似的方法,盡可能不要再Update或FixedUpdate中使用搜索方法
3.Transform中設置position和rotation會觸發內部的OnTransformChanged事件并傳播到所有的子級對象中,對于含有非常對子物體的對象來說,這種操作開銷很大,應該 減少對position和rotation的修改。如果某個方法中要分別設置position的xyz,可以創建一個Vector3然后分別將xyz設置到該Vector3中,最后將Vector3設置給position,而不要每次分開設置position的xyz。嘗試使用localPosition替代position。localPosition存儲在transform中,訪問該值時,Unity會直接將其返回,而position在每次訪問時都會重新計算,如果要經常獲取position,可以將其緩存起來。
4.Update()和LateUpdate()等事件方法的每次調用都需要引擎代碼與托管代碼之間進行通信,還要Unity進行安全檢查(GameObject狀態是否合法等),即使這些事件方法的方法體是空的,引擎任然會對其進行調用。因此,為避免浪費CPU時間,應該 刪除空的事件方法。另外,如果某個活動狀態(gameObject.active == true)的GameObject上的腳本中含有Awake()方法,即使這個腳本沒有被啟用(enabled==false),Awake()方法也會執行。如果游戲中含有非常多的帶有Update()方法的MonoBehavior,應該嘗試改變代碼結構來減少開銷,這有一篇相關的博客。
5.Vector2和Vector3()向量的數學運算要比普通的浮點數和整數的數學運算更加復雜,訪問向量的某些屬性可能會帶來隱含的開銷,例如magnitude屬性(不僅針對向量,例如上文提到的Transform.position)。每次訪問magnitude,引擎都會進行開平方運算,雖然單次計算并不會消耗多少時間, 但當數量級足夠大時,這種開銷將變得明顯。可以嘗試使用sqrMagnitude(即magnitude的平方)替代magnitude,減少開平方操作。
6.Camera.main所引起的問題與Find()方法類似,應該避免使用Camera.main并且手動管理對相機的引用。
以上就是“Unity代碼層優化和規避的方法有哪些”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。