[原創]Unity2D 開發 + UGUI 中文教程三

不知道上一篇裏,你們是否是都作出了跳躍的效果。從這一節開始,我提交了代碼到Github,你們若是有什麼不明白的地方,能夠去看源碼。另外個人Github裏還有兩個之前寫的spritekit遊戲,你們也能夠圍觀一下。傳送門git

添加障礙物

首先咱們測試一下上一節提到的跳躍的數值,我測試出了一組比較合理的數據,你們能夠試用一下。github

private float jumpForce = 15;
private float gravity = 1;

接着咱們添加一個障礙物的素材到遊戲中,而後將素材拖拽到關係樹面板,會自動生成一個以該精靈爲外觀的遊戲對象。咱們在屬性面板中,添加一個Box Collider2D組件,和一個Rigidbody2D組件。點擊AddComponent以後,直接輸入組件的名字,下面會列出搜索結果,直接點擊就能夠。app

我來解釋下這兩個組件的做用,你們不明白能夠百度一下,網上相應的介紹特別多。collider是設置一個碰撞盒,用來檢測碰撞的組件。Rigidbody是剛體盒,表示這個遊戲對象的物理屬性,好比重量、密度等。據我所知,兩個物體若是想檢測碰撞,必須至少有一者是剛體,若是兩個都只設定了collider沒有設定剛體,那麼檢測不到碰撞。建立collider組件以後,會自動按照當前Sprite Renderer組件中的精靈尺寸,建立一個對應尺寸的碰撞盒,也就是collider組件中的Size屬性。剛體組件中,默認使用的是動態的剛體,會受到重力影響,勾選Is Kinematic以後,就變成了靜態的剛體,你們能夠本身嘗試一下選和不選的區別,這裏咱們使用的是靜態剛體。以下圖:編輯器

圖片描述

以後我要向你們介紹一個Unity裏很好用的玩具:Prefab。這個單詞的意思,是預製體,通俗的來講,就是好比我要造一輛車子,那麼Prefab就是一些作好的部件模具,在須要的時候,我能夠直接用模具當即建立一個現成的零件來使用。當須要在遊戲運行過程當中,建立大量相同的物體時,這個東西真的很好用,只須要作一次設置,之後直接拿過來初始化就能夠了。ide

這裏咱們設置好了一個障礙物,而後拖拽關係面板裏的障礙物對象到Assets面板中,一個預製體就作好了~!而後咱們刪掉關係樹中的這個預製體,若是後續須要修改它,直接在Assets目錄中選中,就能夠在屬性面板修改了。函數

在腳本里掛載預製體Prefab

下面咱們須要在遊戲過程當中,動態建立障礙物對象了。佈局

首先咱們在關係面板中,添加一個空對象GameObject,設置其座標到原點。而後點AddComponet添加一個腳本組件,名字叫CreateObstacle,也就是建立障礙物的意思。在Assets面板中打開這個腳本,下面咱們來講一下,如何在代碼中連接到上面提到的預製體。測試

CreateObstacle類中,添加一行代碼,而後保存一下
public GameObject obstaclePrefab;
還記得我以前說過吧,public屬性的內容,能夠在Unity引擎的編輯器的屬性面板直接訪問到,這裏也是同理。預製體的默認類型是GameObject,咱們在這裏建立了一個預製體對象,可是沒有賦值,由於咱們會在Unity編輯器中拖拽賦值,告訴腳本咱們將使用哪個預製體。(變量名是我我的習慣,加一個Prefab後綴方便咱們本身辨認哪個是預製體)spa

回到Unity編輯器,選中這個剛建立的GameObject,會發現腳本組件下面多出了一個屬性框(若是沒有通常是腳本沒有保存或者代碼有錯誤)。如圖:
圖片描述日誌

而後咱們將預製體,也就是右邊這個拖拽到這個屬性欄裏,預製體就連接到腳本中了。注意:精靈和預製體從icon上看起來差很少,不要選錯了,若是區分不開,仔細對比這兩個對象的屬性面板就知道了。同時,若是你拖拽的目標不是GameObject類型,那麼是沒法拖拽上去的。

以後咱們回到Mono,如今能夠用預製體建立實例了。

使用計時器

計時器在任何遊戲中都很是的經常使用,下面咱們作一個簡單的計時器。

首先在obstaclePrefab下面,定義兩個變量currentTime和interval,分別表示累計時間和時間間隔。

private float currentTime = 0;
private float interval = 1;

而後在Update函數中添加以下代碼:

currentTime += Time.deltaTime;//每一幀計算一下累計時間
if(currentTime > interval){//時間超過期間間隔 觸發事件
    currentTime = 0;//重置計數器
    Debug.Log("something happen");//Unity中用來打印日誌到控制檯的函數
}

這樣咱們就製做了一個間隔時間爲1秒的觸發器。在Unity中執行一下,會看到控制檯每隔一秒會輸出字符串something happen。
圖片描述

在個人佈局裏,Project面板和Console都在下面,Assets文件夾就顯示在Project面板中。

動態建立障礙物

下面咱們用計時器來作一些事。

刪掉打印日誌的代碼,添加如下代碼:
Instantiate(obstaclePrefab, Vector3.zero, Quaternion.identity);
這個你從未見過的函數,是之後會大量使用的一個函數,專門用來將預製體實例化爲一個能夠用的零件,並添加到場景裏。第一個參數是預製體連接的變量,第二個參數是一個初始座標,第三個參數是初始角度。Vector3.zero表示的是座標原點,Quaternion那個神馬的至關因而角度的原點,也就是不旋轉任何角度。

而後咱們執行遊戲,發現場景裏只能看到一個對象,可是關係樹面板中卻不斷生成新的對象,這些對象都疊加到了原點上。由於主角只會原地跑,而障礙物須要隨着地面一塊兒運動,那麼咱們下面就讓障礙物本身動起來。

在Assets文件夾裏選中預製體,添加一個腳本組件:Moving,雙擊Moving腳本就會在Mono中打開。由於障礙物是隨着地面運動,因此咱們將ScrollGround腳本中的這一行拷貝到Moving中的Update函數裏:
transform.position -= new Vector3(Time.deltaTime, 0, 0);

當障礙物移動到屏幕外的時候,這個障礙物沒有用了,只會白白佔用內存,那咱們在下面來清理掉屏幕外的障礙物。最終Moving腳本的Update函數以下:

void Update () {
    transform.position -= new Vector3(Time.deltaTime, 0, 0);

    if(transform.position.x < -11.36f){//這個數值能夠是任何超過屏幕左邊界的一個X座標 我這裏直接使用了一個比較大的值
        Destroy(gameObject);//這個函數用來銷燬遊戲對象
    }
}

Destroy函數中的參數,若是寫gameObject(注意小寫首字母),那麼指代的就是當前遊戲對象的本體,這個函數也能夠用來銷燬當前遊戲對象的某個組件,好比Destroy(gameObject.GetComponent<Rigidbody2D>());,GetComponent函數用來獲取一個特定組件,這個咱們後面再說。

如今執行一下游戲,能夠看到障礙物已經「跑」起來了~!

設定角色的碰撞檢測

可是好像哪裏不對勁!障礙物應該選一個更合適的位置來建立~咱們能夠拖拽一個預製體到場景中,來回拖動,看它的座標值變化,找到一個合適的生成障礙物的初始位置。我這裏測出的座標是:
圖片描述
不要忘記測試完座標值,刪掉這個臨時放進去的障礙物。

咱們把這個座標值填入CreateObstacle腳本中,替換掉Vector3.zero,變成:
Instantiate(obstaclePrefab, new Vector3(7, -0.24f, 0), Quaternion.identity);

回到Unity編輯器,選中主角,添加一個Box Collider2D組件,用來檢測主角和障礙物的碰撞,這裏collider的尺寸也自動幫咱們設定好了。進入Player腳本,添加一個函數:

void OnTriggerExit2D(Collider2D other) {
    Debug.Log("game over");
}

這裏咱們使用的是一個觸發器函數,當碰撞觸發時,這個函數裏的代碼會被執行。可是執行遊戲時,發現這個函數沒有被觸發,這是爲何呢?由於咱們還須要設置碰撞盒爲trigger類型。分別編輯主角和障礙物的預製體的Box Collider2D組件,勾選Is Trigger選項。這樣這兩個對象,就會檢測到碰撞事件的觸發了。

Is Trigger選項,三言兩語不太好說明白。若是你須要作不可穿越的碰撞效果,好比人撞到了牆,那麼就能夠不用Is Trigger。若是你須要作可穿越的碰撞,好比人碰到了毒霧,那麼就須要用觸發器的形式來作。這裏我都用代碼來控制了,因此使用了觸發器模式,只是爲了檢測到碰撞。若是不用觸發器模式,那麼兩個collider都要取消Is Trigger選項,而後使用OnCollisionEnter2D函數來檢測,具體的用法你們百度一下便可。

相關文章
相關標籤/搜索