unity(一) 初學踩坑筆記(經驗心得)

最近開始接觸unity,做了個項目,不過是初學者,踩了不少坑,留下一些踩坑的經歷。
有不對的地方歡迎大家指點~謝謝


一、Update()和FixedUpdate()

——————————————————————
Update()
  剛接觸的小夥伴一旦創建了C#腳本就能看到一個Update,並且邏輯統統都往這裏面寫,但是越往後會發現越控制不了自己的代碼,有些效果和自己的預期不同。
  這是因爲Update是和幀率相關的。而幀率由於不同的設備或者在不同時刻由於渲染變化導致的性能差異是會變化的,這就導致Update的更新間隔不同,以致於最終獲得的效果可能是不同的。
  
FixedUpdate()
  FixedUpdate顧名思義就是固定刷新,不會受到幀率的影響,刷新頻率可以自己設置,可以再編輯器裏菜單中Edit——Project Settings——Time中的Fixed timestep設置。由於知道了Update的不穩定性,所以FixedUpdate就是專門處理那些需要穩定處理的邏輯——與物理引擎相關的計算(Rigidbody剛體相關)。
  
  所以如何淺顯的理解這二者呢,可以把Update視做渲染同步,FixedUpdate試做物理同步。
  比如此時有一個方塊正在做直線運動,當每次渲染時,不論Update的執行間隔有多少,是否準確,拿到的計算的值都是從FixedUpdate中取出來的。也許一個Update的間隔中執行了5次,10次FixedUpdate,但最終方塊的位置相對於時間而言都是準確的。不會因爲跳幀等不確定因素而影響到最終結果。


二、Time.deltaTime

——————————————————————
  很多初學者應該都遇到過這樣的代碼:在Update裏面寫了:
   transform.Translate(Vector3.right * 60 * Time.deltaTime);
  這句話的本意是什麼呢,是每秒鐘運行60,所以裏面的60很好理解,但是Time.deltaTime又是什麼意思呢。
  看了上面的Update的小夥伴應該已經想到肯定是和幀率相關。如何理解呢。我們先假定現在的幀率是60幀,所以Update的運行時間應該是1/60秒。所以想到達到每秒60的需求,那麼每幀的需要移動的距離就是1/60 * 60,這不難理解。但是這其中的問題出在哪呢。
  就是這1/60秒出了問題,那就是這個時間我們人爲計算出來的。代碼可能並不是這麼運行的,從標題一中解釋了Update的刷新間隔是不確定的,所以如果這麼寫,那麼最終計算出來的每秒運行的距離也是無法控制的。所以Time.deltaTime的作用就出來了。這就表示每幀的增量,這個值是固定的嗎?來測試一下:
  在這裏插入圖片描述
  很明顯,這個值是會變化的,所以可以把Time.deltaTime理解爲一種補償措施。
  Time.deltaTime*60就可以理解爲我只能確保每秒走60的距離。不能保證每幀走過的距離是相同的。每一幀有可能走的多也可能走的少。
  不過如果想獲得精確的計算,還是推薦使用FixedUpdate;

三、全局實例

——————————————————————
  寫項目時也許經常會遇到切換場景的需求。但是當切換場景時卻發現另外一個場景需要的東西也被銷燬了。方法應該有很多。我就寫我用過的2個方法。
一、不銷燬(主要用於實例)
  使用:GameObject.DontDestroyOnLoad(gameObject);這個方法來控制切換到其他場景時不會銷燬。
  但是如果使用了這個方法就會發現,重新切回這個場景的時候,場景裏不光保留了之前的那個實例,還會創建一個新的實例,所以需要把新的那個銷燬掉。

private void Awake()
    {
        if (GameData.Instance.isGlobalUIInit)
        {
            Destroy(this.gameObject);
        }
        else
        {
            if (!GameData.Instance.isGlobalUIInit)
            {
                GameData.Instance.isGlobalUIInit = true;
            }
            GameObject.DontDestroyOnLoad(gameObject);
        }
    }

在這裏我是用變量的方式判斷需要的實例是否存在的,當然也可以用查找的方式,如果已經有需要的實例,那麼切換場景回來的時候就把新建的這個銷燬掉。這就保證始終都是最初的那個實例(這裏需要保證存留的那個舊的,如果保留新的。那麼裏面的參數都會被初始化)。

一、新建一個只加載一次的場景作爲遊戲入口(主要用於數據)
  這個方法可能比較笨,但確實非常實用,創建一個只作爲遊戲入口的場景,這個場景裏需要的東西只需要掛上一個不銷燬即可,就可以保證全局使用。但通常都保留數據相關即可。這個場景只作爲一個邏輯場景。沒有UI,只作爲入口,加載完需要的數據後,緊接着就進入主場景。
  場景的初始加載順序可以在菜單中的File——Build Settings中設置,第一個即爲默認場景入口。

四、判斷是否點擊到了UI

——————————————————————
  當我們控制點擊事件時,通常需要判斷是否點擊到了UI上,然後進行邏輯處理,但是最開始發現在PC端上有用,一旦打包移動端出來就不生效了,所以需要分開判斷。
  EventSystem.current.IsPointerOverGameObject()方法,是用來判斷鼠標是否點擊在UI上。
  Input.touch是移動端的觸摸操作
  (這裏當時是讓我鬱悶的地方。PC和移動端的控制是不一樣的。)

public bool UICheck()
    {
        if (Application.platform == RuntimePlatform.IPhonePlayer || Application.platform == RuntimePlatform.Android)
        {//移動端
            bool ifClick = false;
            if (Input.touchCount > 0)//觸摸數量大於0
            {
                if (Input.GetTouch(0).phase == TouchPhase.Began)//手指touch的狀態爲按下屏幕,參數裏的0標識第一個觸碰的手指
                {
                    if (EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))//  Touch.fingerId: 一個Touch的標識,用來標識確定的touch
                    {
                        ifClick = true;
                    }
                }
            }
            return ifClick;
        }
        else
        {
        	//PC端,這裏的else就是PC端不太準確,但我這裏由於沒有用到其他平臺,所以直接用else判斷PC端了
            return EventSystem.current.IsPointerOverGameObject();
        }
    }






剩下的都是些小問題小優化了

五、IOS打包出來聲音很小

——————————————————————
  打包出來聲音很小有可能是Prepare iOS for Recording的問題,在打包時,ios的PlayerSettings中找到Prepare iOS for Recording,把前面的對勾取消掉就好,勾選了可能會導致聲音會從話筒中出來,而不是揚聲器中出來,當然這可能只是出現的一個原因。還有衆多其他可能的原因。

六、儘量少用outline描邊

——————————————————————
  OutLine是UGUI中給Text添加描邊的功能,但是這個描邊的原理是在這個text的基礎上,又畫了四遍,然後通過位移在上下左右4個方向都顯示出來,效率很低。並且這個outline也只能用於描邊需求不是很粗的情況下,如果很粗就會出現對不起的情況。
  在這裏插入圖片描述
  在這裏插入圖片描述
  並且如果使用的過多,會導致verts(攝像機視野內渲染的頂點數)過多而性能消耗過於嚴重,像outline這樣的原理而產生的效果。會使這個text的頂點數直接增加4倍。所以如果需求量多的話。慎用~這對性能優化很重要。

最後來一句,碰撞體多的時候,記得給碰撞體分層,不然真的很難受。

有不對的地方歡迎大家指點~謝謝

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章