【問題】我希望可以在遊戲有連網的功能,而使用的協定是http協定。

根據官網的參考文章,有以下的範例參考:

using UnityEngine;
using System.Collections;

public class ExampleClass : MonoBehaviour {
    public string url = "http://images.earthcam.com/ec_metros/ourcams/fridays.jpg";
    IEnumerator Start() {
        WWW www = new WWW(url);
        yield return www;
        renderer.material.mainTexture = www.texture;
    }
}

官網的範例 連結

但是,當我在實作時,卻好像沒有這麼順利。

【我要作甚麼】我希望按下按鈕後,可以呼叫某個.php檔,再由該檔案傳回資訊。於是我在我的localhost設了一個.php檔案,呼叫該檔案只會回傳一個固定的字串"YAYAYAYA"。該字串我會顯示在Unity的console畫面。

首先,開啟一個新專案,對Camera設定一個C# script。


新增一個onGUI(),我想要一個按鈕在左上方。

	void OnGUI(){
		// A button
		if (GUI.Button (new Rect ( 0, 0, 100, 100), "Link")) {
			print("You click the button");
		}
	}

 

我的localhost下有個檔案名為connect.php,內容如下:

/**
* connect.php
*/
<?php 
echo "YAYAYAYA";
?>

 

回到Unity,我又新增了一個function叫Send(),功能為送出需求與顯示回傳資訊,程式碼如下:

	private IEnumerator Send(){
		print("Do Link");
		WWW rtn = new WWW(mUrl);

		yield return rtn;
print("Finish Link"); if((!string.IsNullOrEmpty(rtn.error))){ print ("Error return: "+rtn.error); } else{ Debug.Log(rtn.text); } }

我在第2行與第6行埋下了Log,運行這段程式時一定會顯示這兩行Log。

 

新增一個成員變數mUrl,為我們要連結的網址:

/*類別的成員變數*/
public string mUrl = "http://localhost/unity_serv/connect.php";

 

 再稍微修改一下onGUI,使得按下按鈕時可以呼叫Send()。

	void OnGUI(){
		// A button
		if (GUI.Button (new Rect ( 0, 0, 100, 100), "Link")) {
			print("You click the button");
			Send();
		}
	}

 

執行畫面如下:

unity1_1

點了Link按鈕之後,下面Consloe只有顯示"You click the button"。而Send()中的Log完全沒有印,表示根本就沒有進來Send()。

 

【問題來了】

我幾番追查,發現是Send()中有行"yield return rtn;"這行有問題。如果沒有這一行(改成"return null"),則執行時就會進去Send()裡面。可是就沒有收到任何的資訊,表示我們呼叫網頁是失敗的。

 

我努力在網路上搜尋yield的使用方式與介紹,可是用法幾乎都跟Unity官網上說的差不多。灰心之餘,突然找到一個函式 StartCoroutine() 。

 

修改一下onGUI()函式,把Send()包在StartCoroutine()的參數內:

	void OnGUI(){
		// A button
		if (GUI.Button (new Rect ( 0, 0, 100, 100), "Link")) {
			print("You click the button");
			StartCoroutine(Send());
		}
	}

 

再執行一次,結果如下圖:

unity1_2

 

這次總算有進去Send()而且也有成功的呼叫網頁了。

 

【想一想】為什麼要設定StartCoroutine()呢?

首先,yield return xx; 是需要與IEnumerator類型的函式使用,如果類型是void或是int等都會錯誤。

 

這整組的用法,目的在於為了要可以執行中斷。也就是說,當我們使用Send()這個函式時,他不會馬上去執行該函式,而是另外開一個執行緒去處理他。

 

然而,在Unity,WWW的用法在JavaScript與C#有些許的不同。官網上提到:

When using JavaScript it is not necessary to use StartCoroutine, the compiler will do this for you. When writing C# code you must call StartCoroutine.

 

所以,C#必須透過使用StartCoroutine()去開啟一組IEnumerator函式與yield的使用。

 

熱血啊!成功解決問題!繼續邁向偉大航道前進!

文章標籤

全站熱搜

巴比特 發表在 痞客邦 留言(0) 人氣()