Unity 遊戲框架搭建 2019 (四十二、四十三) MonoBehaviour 簡化 & 定時功能
- 2020 年 5 月 4 日
- 筆記
MonoBehaviour 簡化
在前兩篇,我們完成了第九個示例。為了完善第九個示例,我們複習了類的繼承,又學習了泛型和 params 關鍵字。
我們已經接觸了類的繼承了。接觸繼承之前,把類僅僅當做是方法的集合,接觸了繼承之後,我們的類還可以使用繼承來解決一些問題。
第十個示例
在 Unity 中,我們的腳本都往往繼承自 MonoBehaviour,繼承了之後我們就可以在腳本內編寫很多功能。比如訪問 transform/gameObject,再比如控制動畫接收碰撞事件等等。另外我們繼承了 MonoBehaviour 才能被作為腳本掛到 GameObject 上。
僅僅是通過繼承,MonoBehaviour 的很多功能都能夠進行復用。所以繼承的一個作用就是程式碼復用。而我們知道方法也可以程式碼復用,泛型可以對結構進行復用。那麼繼承能是復用什麼?
繼承既能復用程式碼也能復用結構。不過術業有專攻,有的情況下使用方法進行復用更合理,有的情況下適用於泛型,當然也有適用繼承的情況。
像 GameObjectSimplify 和 TransformSimplify,這兩種方法集,目前其實通過繼承來實現會更好一點。因為這兩個類中的方法全部都是要傳一個固定的對象進去的,比如 GameObjectSimiplify 的每個方法第一個參數都是 GameObject 參數,而 TransformSimplify 也是如此。他們使用起來也不是很方便。
使用程式碼如下:
GameObjectSimplify.Show(gameObject);
TriansformSimplify.Identity(transform);
可以看出都需要把所有的類名字全部打出來,而使用繼承就會好很多。
我們先實現第十個示例程式碼,如下
MonoBehaviourSimplify.cs
using UnityEngine;
namespace QFramework
{
public partial class MonoBehaviourSimplify : MonoBehaviour
{
public void Show()
{
GameObjectSimplify.Show(gameObject);
}
public void Hide()
{
GameObjectSimplify.Hide(gameObject);
}
public void Identity()
{
TransformSimplify.Identity(transform);
}
}
public class Hide : MonoBehaviourSimplify
{
private void Awake()
{
Hide();
}
#if UNITY_EDITOR
[UnityEditor.MenuItem("QFramework/10.MonoBehaviour 簡化", false, 11)]
static void MenuClicked()
{
UnityEditor.EditorApplication.isPlaying = true;
var gameObj = new GameObject("Hide");
gameObj.AddComponent<Hide>();
}
#endif
}
}
MonoBehaviourSimplify 為了可以在之後的示例中進行擴展,所以加上了 partial 關鍵字。而其中的 Show、Hide 等方法這次沒有使用 static 關鍵字,那麼這種方法叫做成員方法。成員方法必須通過對象來調用。而有 static 關鍵字的叫做靜態方法,靜態方法必須通過類來調用。
示例就是程式碼中的 Hide 腳本。
而 MenuItem 中有一行程式碼:
UnityEditor.EditorApplication.isPlaying = true;
這行程式碼執行之後,UnityEditor 就會自動運行。
其他的都很簡單,MenuItem 執行之後如下所示:
示例是正確的。
OK,這個示例就完成了。
菜單如下:
目錄結構如下:
今天的內容就這些,我們接觸了繼承之後,又強化了一次繼承的使用,這樣我們之後每次寫示例的時候會有很多設計工具選擇。
定時功能
在上一篇我們完成了 MonoBehaviour 的簡化示例,通過做這個示例,強化了一次繼承的使用。
而為了讓示例腳本自動運行,就接觸了 EditorApplication.isPlaying 這個 API,有了這個 API 我們之後所有需要運行 UnityEditor 的腳本都可以按照這種格式去做。
今天我們再接著往下學習。
第十一個示例
我們都知道,在項目中,我們會遇到非常多的定時需求。而定時功能在 Unity 中最容易實現的方式是通過 Coroutine(協程)實現。在這個示例中我們實現一個簡單的定時工具。
在實現在哪裡呢?
我們目前有兩個選擇:
- 一是寫一個工具類,比如 TimerUtil 或者 DelayUtil,或者乾脆卸載 CommonUtil 里。
- 二是實現到 MonoBehaviourSimplify 里。
考慮到,執行協程是需要通過 MonoBehaviour 啟動的,所以方法在 MonoBehaviourSimplify 中定義更好一點。而實現的部分需要定義一個協程方法。這個協程方法並不希望被子類或者外部類調用,所以這個協程方法應該使用 private 許可權。
實現之後的示例程式碼如下:
using System;
using System.Collections;
using UnityEngine;
namespace QFramework
{
public partial class MonoBehaviourSimplify
{
public void Delay(float seconds, Action onFinished)
{
StartCoroutine(DelayCoroutine(seconds, onFinished));
}
private static IEnumerator DelayCoroutine(float seconds, Action onFinished)
{
yield return new WaitForSeconds(seconds);
onFinished();
}
}
public class DelayWithCoroutine : MonoBehaviourSimplify
{
private void Start()
{
Delay(5.0f, () =>
{
UnityEditor.EditorApplication.isPlaying = false;
});
}
#if UNITY_EDITOR
[UnityEditor.MenuItem("QFramework/11.定時功能", false, 11)]
private static void MenuClickd()
{
UnityEditor.EditorApplication.isPlaying = true;
new GameObject("DelayWithCoroutine")
.AddComponent<DelayWithCoroutine>();
}
#endif
}
}
以上程式碼中,大家可能對 Action 比較陌生。Action 其實是 C# 自定義的委託。
定義如下:
namespace System
{
public delegate void Action();
}
至於委託是什麼…,理解成動態方法就好了,在初期呢,我們用它來做回調函數。
還有這樣的一個寫法也可能比較陌生: () => { } ,這種寫法叫做 lambda 表達式,相當於實現了一個沒有名字的方法。詳細的使用方法可以自己用搜索引擎查一下,這裡筆者只要能看懂以上程式碼就行。當然在以後的文章中會非常深入地講 委託、lambda 表達式在庫/框架中的使用的。
示例程式碼執行之後,如下:
過了五秒後,UnityEditor 運行會自動停止。
如下:
結果是正確的。
這篇文章的示例就寫完了。
菜單欄如下:
文件目錄如下:
我們可以進行一次導出了。
我們一篇文章再見,拜拜~
轉載請註明地址:涼鞋的筆記:liangxiegame.com
更多內容
-
QFramework 地址://github.com/liangxiegame/QFramework
-
QQ 交流群:623597263
-
Unity 進階小班:
- 主要訓練內容:
- 框架搭建訓練(第一年)
- 跟著案例學 Shader(第一年)
- 副業的孵化(第二年、第三年)
- 權益、授課形式等具體詳情請查看《小班產品手冊》://liangxiegame.com/master/intro
- 主要訓練內容:
-
關注公眾號:liangxiegame 獲取第一時間更新通知及更多的免費內容。