最簡單的和所有最佳化最好的是少工作量的執行。例如,當一個敵人很遠最完美的時間就是敵人入睡時可以接受。直到玩家靠近時什麼都沒有做。這是種緩慢的處理方式的情況:
function Update ()
{
// 早期進行如果玩家實在是太遙遠。
if (Vector3.Distance(transform.position, target.position) > 100)
return;
perform real work work…
}
這不是一個好主意,因為Unity必須調用更新功能,而你正在執行工作的每一個幀。一個比較好的解決辦法是禁用行為直到玩家靠近。有3種方法來做到這一點:
1. 使用OnBecameVisible和OnBecameInvisible。這些回調都是綁到渲染系統的。只要任何相機可以看到物體,OnBecameVisible將被調用,當沒有相機看到任何一個,OnBecameInvisible將被調用。這種方法在很多情況下非常有用,但通常在AI中並不是特別有用,因為只要你把相機離開他們敵人將不
可用。
function OnBecameVisible () {
enabled = true;
}
function OnBecameInvisible ()
{
enabled = false;
}
2.使用觸發器。一個簡單的球形觸發器會工作的非常好。一旦你離開這個影響球你將得到OnTriggerEnter/Exit調用。
function OnTriggerEnter (c : Collider)
{
if (c.CompareTag(“Player”))
enabled = true;
}
function OnTriggerExit (c : Collider)
{
if (c.CompareTag(“Player”))
enabled = false;
}
3.使用協同程式。Update調用的問題是它們每幀中都發生。很可能會只需要每5秒檢檢查一次到玩家的距離。這應該會節省大量的處理周期。
協同程式:特殊類型的函數編程意義,允許阻止它的執行,直到自己的某些條件得到滿足。
function MyCoroutine(){
DoSomething();
yield; //停留一幀
DoSomethingElse();
}
當你調用這個函數(啟動協程)會否行為就像任何其他的正常功能直到達到產量的指示。該產量指令解釋:如指令的產量在這個意義上它停止的功能和返回控制執行的代碼,調用該函數返回聲明的作品。主要的區別是,產量指令讓你拖延執行的代碼,後(在最後一個例子中,DoSomethingElse()語句)。
function MyCoroutine(){
DoSomething(); //立即執行此
yield; //向調用者返回控制
DoSomethingElse(); //這將是一幀後執行
}
void Start(){
MyCoroution();
}
如果您有什麼發生後MyCoroutine呼籲更多的代碼?讓我們看到了一些列印的例子:
function MyCoroutine(){
print(“This is printed second”);
yield; //控制返回到開始功能
print(“This is printed one fourth, exactly one frame after the third”);
}
void Start(){
print(“This is printed first”);
MyCoroutine();
print(“This is printed third”);
}
你什麼時候可以控制指令後,產量代碼將被執行。這取決於產量指令參數,根據下表 沒有什麼:它會等待一幀另一個協程調用:它會等到調用的協程完成執行 阿WaitForSeconds對象:它會等待一段時間 困惑?下面是例子:
function MyCoroutine(){
DoSomething(): //立即執行
yield WaitForSeconds(2); //控制權返回給調用者
DoSomethingElse(); //這將是2秒後執行
}
void Start(){
MyCoroutine();
}
function MyCoroutine(){
DoSomething(): //立即執行
yield MyOtherCoroutine(); //去執行MyOtherCoroutine!
DoSomethingElse(); //這將是執行完畢後執行MyOtherCoroutine
}
function MyOtherCoroutine(){
DoStuff(): //立即執行
yield WaitForSeconds(2); //控制返回到在這種情況下,啟動函數的調用者()
DoMoreStuff(); //這將是2秒後執行
//MyOtherCoroutine執行完這裡
}
void Start(){
MyCoroutine();
}
Coroutines & Yield
在編寫遊戲代碼的時候,常常需要處理一系列事件。這可能導致像下面的代碼。
private var state = 0;
function Update()
{
if (state == 0) {
// 做步驟0
state = 1;
return;
}
if (state == 1) {
// 做步驟1
state = 2;
return;
}
// …
}
更方便的是使用yield語句。yield語句是一個特殊類型的返回,這個確保在下次調用時該函數繼續從該yield語句之後執行。
while(true) {
// 做步驟0
yield; //等待一幀
// 做步驟1
yield; //等待一幀
// …
}
你也可以傳遞特定值給yield語句來延遲Update函數的執行,直到一個特定的事件發生。
// 做一些事情
yield WaitForSeconds(5.0); //等待5秒
//做更多事情…
可以疊加和串連coroutines。
這個例子執行Do,在調用之後立即繼續。
Do ();
print (“This is printed immediately”);
function Do ()
{
print(“Do now”);
yield WaitForSeconds (2);
print(“Do 2 seconds later”);
}
這個例子將執行Do並等待直到它完成,才繼續執行自己。
//連結coroutine
yield StartCoroutine(“Do”);
print(“Also after 2 seconds”);
print (“This is after the Do coroutine has finished execution”);
function Do ()
{
print(“Do now”);
yield WaitForSeconds (2);
print(“Do 2 seconds later”);
}
任何事件處理控制代碼都可以是一個coroutine
注意你不能在Update或FixedUpdate內使用yield,但是你可以使用StartCoroutine來開始一個函數。
參考YieldInstruction, WaitForSeconds, WaitForFixedUpdate, Coroutine and MonoBehaviour.StartCoroutine擷取更多使用yield的資訊。