1. 程式人生 > >[Unity指令碼執行時更新]C#5新特性

[Unity指令碼執行時更新]C#5新特性

洪流學堂,讓你快人幾步!本文首發於洪流學堂微信公眾號。

本文是該系列《Unity指令碼執行時更新帶來了什麼?》的第3篇。
洪流學堂公眾號回覆runtime,獲取本系列所有文章。

Unity2017-2018.2中的4.x執行時已經支援到C#6,Unity2018.3將支援到C# 7.2,看看C#的新特效能給程式碼帶來什麼吧。

C#5 新特性

  • Asynchronous methods:非同步方法
  • Caller info attributes:呼叫時訪問呼叫者的資訊,可以用於除錯

Asynchronous methods 非同步方法

C#5中引入了兩個新關鍵字async

修飾符和await操作符。這是C#5最重要的更新,可以說讓非同步程式設計能達到事半功倍的效果。

使用async修飾的方法被稱為非同步方法,這個方法呼叫時應該在前面加上await。下面我們來看看這個新特性對Unity中的非同步程式設計有什麼影響。

我們先看一下以前使用非同步程式設計,需要使用協程,程式碼大概是這個樣子:

public class AsyncExample : MonoBehaviour
{
    IEnumerator Start()
    {
        Debug.Log("Waiting 1 second...");
        yield return
new WaitForSeconds(1.0f); Debug.Log("Done!"); } }

有了async-await之後,可以這麼寫:

public class AsyncExample : MonoBehaviour
{
    async void Start()
    {
        Debug.Log("Waiting 1 second...");
        await Task.Delay(TimeSpan.FromSeconds(1));
        Debug.Log("Done!");
    }
}

Unity中的協程是使用迭代器實現的,本質上不是執行緒,執行時還是在主執行緒中執行。
但是,對,但是

,由於Unity的API只能在主執行緒中呼叫,async的方法在呼叫時會自動開啟一個新的執行緒去執行,所以在Unity中還是有很大的侷限。

目前我們可以將不呼叫Unity API,但是計算量比較大的方法採用非同步的方式進行計算。

另外也可以手動去增加Unity中async-await的支援,但是其實有一個Unity外掛已經做的很好了,那就是UniRx。例如:

public class AsyncExample : MonoBehaviour
{
    public Button TestButton;
 
    async void Start()
    {
        await TestButton.OnClickAsObservable();
        Debug.Log("Clicked Button!");
    }
}

關於UniRx這個外掛,我們之前在洪流學堂公眾號中也已經寫過圖文版的教程,大家可以在洪流學堂公眾號中回覆unirx獲取。

async-await在Unity中的最佳實踐

  • 不要在非同步方法中呼叫Unity的API,就跟不要在子執行緒中呼叫Unity的API一樣,否則Console中也會報錯
  • 非同步方法命名應該以Async結尾,這樣大家知道呼叫的時候使用await

Caller info attributes:呼叫時訪問呼叫者的資訊

該功能主要是通過3個Attribute實現:

  • CallerFilePathAttribute 呼叫方的原始碼路徑(編譯時的路徑)
  • CallerLineNumberAttribute 呼叫時的程式碼行
  • CallerMemberNameAttribute 呼叫方法或屬性的名稱

該功能主要是用於除錯,示例程式碼如下:

void Start()
{

    MethodA();
    MethodB();
}

void MethodA()
{
    //InsertLog("MethodA");
    MethodB();
}

void MethodB(
[CallerMemberName] string memberName = "",
[CallerFilePath] string sourceFilePath = "",
[CallerLineNumber] int sourceLineNumber = 0)
{
    InsertLog(memberName);
    Debug.Log(sourceFilePath+sourceLineNumber);
}

void InsertLog(string methodName)
{
    Debug.Log(string.Format("{0} called method B at {1}", methodName,
    DateTime.Now));
}

小結

本文講解了C#5的新特性中對Unity變成有影響的新特性。其中有些概念有些難理解,可以再深入地找一些例子進行強化理解。

洪流學堂公眾號回覆runtime,獲取本系列所有文章。

把今天的內容分享給其他Unity開發者朋友,或許你能幫到他。



《鄭洪智的Unity2018課》,傾盡我8年的開發經驗,結合最新的Unity2018,帶你從入門到精通。