亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Unity3D開(kāi)發(fā)教程:憤怒的小鳥(niǎo)

 更新時(shí)間:2021年06月23日 16:38:00   作者:恬靜的小魔龍  
這篇文章詳細(xì)的講解了如何從0開(kāi)發(fā)出一個(gè)Unity3D的小游戲憤怒的小鳥(niǎo),本文包含大量的圖片與文字描述,也含有大量的源代碼,可以讓你快速入手,希望本篇文章對(duì)你有所幫助

一、前言

“憤怒的小鳥(niǎo)”在2009年12月發(fā)布,由于它的高度上癮的游戲,它很快成為有史以來(lái)最成功的移動(dòng)游戲。

在本教程中,我們將在“Unity”中實(shí)現(xiàn)“憤怒的小鳥(niǎo)”翻版。游戲中最復(fù)雜的部分是物理系統(tǒng),但是多虧了Unity,我們就不用擔(dān)心太多了。

像往常一樣,一切都會(huì)盡可能簡(jiǎn)單地解釋?zhuān)@樣每個(gè)人都能理解它。

以下是項(xiàng)目的預(yù)覽

在這里插入圖片描述

二、源碼

UI資源:
http://xiazai.jb51.net/202106/yuanma/picturezy_jb51.rar

源代碼:
http://xiazai.jb51.net/202106/yuanma/Game_AngryBirds_jb51.rar

三、正文 項(xiàng)目版本

Unity5.0.0f4

1.設(shè)置相機(jī)

點(diǎn)擊Main Cameras,在Hierarchy面板設(shè)置背景色以友好的藍(lán)色色調(diào)(紅色=187, 綠色=238, 藍(lán)色=255)并調(diào)整大小而位置如下圖所示:

在這里插入圖片描述

2.地面設(shè)置

地面貼圖設(shè)置
為了防止版權(quán)問(wèn)題,我們不能在本教程中使用原“憤怒的小鳥(niǎo)”圖形。相反,我們將畫(huà)我們自己的Sprite,使他們看起來(lái)像原來(lái)的游戲。

讓我們從用我們選擇的繪圖工具開(kāi)始:

在這里插入圖片描述

將其保存到我們的項(xiàng)目中后,我們可以在項(xiàng)目區(qū)可以看到:

在這里插入圖片描述

然后在Inspector修改導(dǎo)入設(shè)置:

在這里插入圖片描述

注:Pixels Per Unit像素轉(zhuǎn)到單位價(jià)值16這意味著16x16像素將適合在游戲世界的一個(gè)單位。我們將使用這個(gè)值作為我們所有的紋理。我們選擇16,因?yàn)轼B(niǎo)的大小將有一個(gè)16x16像素后,我們希望在游戲世界它有一個(gè)單位的大小。

好了,現(xiàn)在我們可以將圖片從項(xiàng)目區(qū)拖入到場(chǎng)景中:

在這里插入圖片描述

讓我們看看Inspector把地面定位在(0, -2),所以作為不為y=0的都不是地面的一部分:

在這里插入圖片描述

地面物體設(shè)置
現(xiàn)在地面只是一幅圖像,僅此而已。它不是物理世界的一部分,事物不會(huì)與它相撞,也不會(huì)站在它上面。我們需要添加一個(gè)Collider讓它成為物理世界的一部分,這意味著事物將能夠站在它的頂端,而不是掉進(jìn)它的正中。

添加BoxCollider2D組件:

在這里插入圖片描述

3.邊界設(shè)置

創(chuàng)建空對(duì)象,命名為borders

在這里插入圖片描述

位置歸零:

在這里插入圖片描述

現(xiàn)在,我們將在我們的水平的左邊、右邊和頂部添加某種不可見(jiàn)的區(qū)域。每當(dāng)有東西進(jìn)入那個(gè)區(qū)域,它就應(yīng)該被摧毀。此類(lèi)行為可以通過(guò)Trigger,這幾乎只是一個(gè)Trigger它接收到碰撞信息,但不會(huì)與任何東西發(fā)生沖突。

添加碰撞器:

在這里插入圖片描述

勾選

Is Trigger

之后,我們可以為級(jí)別的右側(cè)和頂部再添加兩個(gè)triggers :

在這里插入圖片描述

如果我們看看場(chǎng)景然后,我們可以看到觸發(fā)器是如何與我們的背景很好地對(duì)齊的:

在這里插入圖片描述

現(xiàn)在我們?nèi)匀槐仨毚_保任何進(jìn)入邊界的東西都會(huì)立即被銷(xiāo)毀。此類(lèi)行為可以通過(guò)腳本Borders:

創(chuàng)建腳本Borders.cs:

在這里插入圖片描述

將其添加到邊界對(duì)象物體上面:

在這里插入圖片描述

讓我們也將腳本移動(dòng)到一個(gè)新的Scripts文件夾,只是為了保持清潔:

在這里插入圖片描述

編輯Borders.cs腳本:

using UnityEngine;
using System.Collections;

public class Borders : MonoBehaviour {

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
}
我們不需要啟動(dòng)或者更新函數(shù),所以讓我們移除它們。相反,我們將使用OnTriggerEnter2D函數(shù),每當(dāng)有東西進(jìn)入其中一個(gè)邊界觸發(fā)器時(shí),統(tǒng)一將自動(dòng)調(diào)用該函數(shù):
using UnityEngine;
using System.Collections;

public class Borders : MonoBehaviour {

    void OnTriggerEnter2D(Collider2D co) {

    }
}
在這個(gè)函數(shù)中,無(wú)論什么東西進(jìn)入Triggers,我們都將Destroy這個(gè)物體:
using UnityEngine;
using System.Collections;

public class Borders : MonoBehaviour {

    void OnTriggerEnter2D(Collider2D co) {
        Destroy(co.gameObject);
    }
}
保存腳本后,我們的邊界就完成了。我們稍后會(huì)看到,如果我們?cè)噲D將一只鳥(niǎo)射出水平之外,它就會(huì)消失。

4.云彩設(shè)置

我們將花幾分鐘額外添加云到背景,以使水平看起來(lái)更好。像往常一樣,我們首先畫(huà)一個(gè):

在這里插入圖片描述

讓我們?cè)陧?xiàng)目區(qū),然后在Inspector修改云的導(dǎo)入設(shè)置:

在這里插入圖片描述

現(xiàn)在我們要做的就是把它從項(xiàng)目區(qū)進(jìn)入場(chǎng)景幾次,將每一片云放置在我們想要的位置:

在這里插入圖片描述

注意:只要使用一些重復(fù)的模式和一些非常顏色,我們可以使水平看起來(lái)相當(dāng)好,無(wú)需付出很大的努力。

5.彈弓設(shè)計(jì)

彈弓圖片

在這里插入圖片描述

一個(gè)飛彈將產(chǎn)生新的鳥(niǎo)類(lèi),并允許用戶(hù)發(fā)射到水平。和往常一樣,我們將從畫(huà)Sprites開(kāi)始:
這里是導(dǎo)入設(shè)置:

在這里插入圖片描述

稍后,我們將創(chuàng)建一個(gè)腳本,在彈弓的位置生成一只新的鳥(niǎo),或者確切地說(shuō)是在彈弓的Pivot位置生成一只鳥(niǎo)。
我們想要在彈弓頂部而不是中間處出現(xiàn),這就是為什么我們要在“導(dǎo)入設(shè)置”中設(shè)置Pivot在頂部。

下面的圖像顯示了中心和頂:

在這里插入圖片描述

*注意:如果我們將數(shù)據(jù)透視設(shè)置為中心然后變換位置是彈弓中心的點(diǎn)。如果我們把Pivot 設(shè)為頂,然后變換位置是彈弓頂端的點(diǎn)。

好了,現(xiàn)在我們可以將彈弓拖到場(chǎng)景中去了(-22, 3):

在這里插入圖片描述

生成鳥(niǎo)腳本
如前所述,我們的彈弓應(yīng)該是生成鳥(niǎo)。確切地說(shuō),它應(yīng)該在一開(kāi)始就生成一個(gè),然后等待用戶(hù)啟動(dòng)它,然后在所有的物理計(jì)算完成之后再生成另一個(gè)。(當(dāng)什么都不動(dòng)的時(shí)候).

我們可以通過(guò)腳本來(lái)實(shí)現(xiàn)這樣的行為。
添加腳本Spawn.cs:

在這里插入圖片描述

我們可以雙擊腳本來(lái)打開(kāi)它:

using UnityEngine;
using System.Collections;

public class Spawn : MonoBehaviour {

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
}
這個(gè)啟動(dòng)函數(shù)在開(kāi)始游戲時(shí)由Unity自動(dòng)調(diào)用。這個(gè)更新函數(shù)被一次又一次地自動(dòng)調(diào)用,大約每秒60次。我們不需要它們中的任何一個(gè),這樣我們就可以從腳本中刪除它們。

還有另一種類(lèi)型的更新函數(shù),它被稱(chēng)為FixedUpdate…它也被一次又一次的調(diào)用,但是是在單位物理完全相同的時(shí)間間隔內(nèi)計(jì)算的,所以在做物理工作的時(shí)候使用FixedUpdate是一個(gè)好主意(我們很快就會(huì)這么做).

下面是修改后的腳本FixedUpdate腳本:

using UnityEngine;
using System.Collections;

public class Spawn : MonoBehaviour {

    void FixedUpdate() {

    }
}
好的,讓我們添加一個(gè)變量,允許我們稍后指定BirdPrefab(我們想生的鳥(niǎo)):
using UnityEngine;
using System.Collections;

public class Spawn : MonoBehaviour {
    // Bird Prefab that will be spawned
    public GameObject birdPrefab;

    void FixedUpdate() {

    }
}
以下是我們?nèi)绾紊伤姆椒ǎ?/pre>
void spawnNext() {
    // Spawn a Bird at current position with default rotation
    Instantiate(birdPrefab,transform.position,Quaternion.identity);
}
生成的觸發(fā)區(qū)域

現(xiàn)在我們不能只生一只又一只鳥(niǎo)。相反,我們將不得不生成一個(gè),然后等待它被發(fā)射。有幾種方法可以實(shí)現(xiàn)這一點(diǎn),但最簡(jiǎn)單的方法是使用Triggers.

Trigger是一個(gè)簡(jiǎn)單的Collider ,接收碰撞信息,但實(shí)際上并不是物理世界的一部分。所以如果我們添加一個(gè)Trigger然后,每當(dāng)有東西進(jìn)入Trigger、留在Trigger中或離開(kāi)Trigger時(shí),我們都會(huì)收到通知。然而,由于它只是一個(gè)Trigger,事情不會(huì)像普通Collider 那樣與它相撞(這很快就更有意義了).

我們可以將Trigger添加到彈弓中,方法是在Hierarchy面板中,然后點(diǎn)擊添加組件Circle Collider 2D,給它一個(gè)合適的半徑和中心然后啟用觸發(fā):

Is Trigger

在這里插入圖片描述

我們還可以在場(chǎng)景中查看:

在這里插入圖片描述

在添加觸發(fā)器之后,每當(dāng)有東西進(jìn)入時(shí),我們都會(huì)收到通知。(OnTriggerEnter2D),停留(OnTriggerStay2D)或離開(kāi)(OnTriggerExit2D)上面那個(gè)綠色的圓圈。

現(xiàn)在,我們可以通過(guò)創(chuàng)建一個(gè)使用中變量,然后將其設(shè)置為bool值,當(dāng)生下一只鳥(niǎo)的時(shí)候?yàn)閒alse,當(dāng)它離開(kāi)觸發(fā)器時(shí)為true:

using UnityEngine;
using System.Collections;

public class Spawn : MonoBehaviour {
    // Bird Prefab that will be spawned
    public GameObject birdPrefab;

    // Is there a Bird in the Trigger Area?
    bool occupied = false;

    void FixedUpdate() {

    }

    void spawnNext() {
        // Spawn a Bird at current position with default rotation
        Instantiate(birdPrefab, transform.position, Quaternion.identity);
        occupied = true;
    }

    void OnTriggerExit2D(Collider2D co) {
        // Bird left the Spawn
        occupied = false;
    }
}
之后我們可以修改我們的FixedUpdate函數(shù),因此每當(dāng)觸發(fā)區(qū)域不再被占用時(shí),它總是生成一只鳥(niǎo):
void FixedUpdate() {
    // Bird not in Trigger Area anymore?
    if (!occupied)
        spawnNext();
}
注:!occupied意思是還沒(méi)有被占用…我們也可以用if(occupied==false).

我們的生成腳本現(xiàn)在可以正常工作了,但是讓我們?cè)偬砑右粋€(gè)特性。在射殺一只鳥(niǎo)之后,會(huì)有很多東西相互碰撞,墜落,滾來(lái)滾去,甚至爆炸。在最初的“憤怒的小鳥(niǎo)”游戲中,只有在水平上的所有東西停止移動(dòng)之后,才會(huì)產(chǎn)生一只新的鳥(niǎo)。

我們可以很容易地創(chuàng)建一個(gè)sceneMoving函數(shù),該函數(shù)查找場(chǎng)景中是否有任何對(duì)象仍在移動(dòng),而不僅僅是一點(diǎn)點(diǎn):

bool sceneMoving() {
    // Find all Rigidbodies, see if any is still moving a lot
    Rigidbody2D[] bodies = FindObjectsOfType(typeof(Rigidbody2D)) as Rigidbody2D[];
    foreach (Rigidbody2D rb in bodies)
        if (rb.velocity.sqrMagnitude > 5)
            return true;
    return false;
}
注意:我們使用了FindObjectsOfType找到所有帶有剛體的物體,之后我們會(huì)檢查每個(gè)物體的velocity,如果這個(gè)剛體的sqrMagnitude大于5,說(shuō)明這個(gè)剛體還在移動(dòng)就返回True,沒(méi)有就返回false

使用這個(gè)整潔的小腳本,我們可以輕松地修改FixedUpdate功能,因此只有在沒(méi)有任何移動(dòng)的情況下才會(huì)產(chǎn)生新的鳥(niǎo):

void FixedUpdate() {
    // Bird not in Trigger Area anymore? And nothing is moving?
    if (!occupied && !sceneMoving())
        spawnNext();
}
現(xiàn)在我們已經(jīng)完成了生成鳥(niǎo)的腳本,我們可以在Inspector面板看到彈弓上面掛載的腳本:

在這里插入圖片描述

注意:我們還不能在沒(méi)有鳥(niǎo)的情況下測(cè)試生成鳥(niǎo)腳本,但是它確實(shí)工作得很好,我們將在創(chuàng)建鳥(niǎo)之后看到這一點(diǎn)。

6.鳥(niǎo)的設(shè)置

鳥(niǎo)的圖片
讓我們開(kāi)始更有趣的事情:鳥(niǎo)。我們首先畫(huà)一個(gè)16 x 16一只大圓身軀和一些小小的翅膀和眼睛的鳥(niǎo)的像素圖像:

在這里插入圖片描述

我們將使用以下方法導(dǎo)入設(shè)置為此:

在這里插入圖片描述

讓我們從項(xiàng)目區(qū)進(jìn)入場(chǎng)景若要從其中創(chuàng)建游戲?qū)ο?,?qǐng)執(zhí)行以下操作:

在這里插入圖片描述

鳥(niǎo)的物理

讓我們?yōu)轼B(niǎo)添加碰撞器Circe Collider 2D:

在這里插入圖片描述

現(xiàn)在有一個(gè)Physics Material 2D對(duì)撞機(jī)的縫隙,讓我們可以給鳥(niǎo)一些特殊的物理特性。在“Unity憤怒的小鳥(niǎo)”教程中,物理材料將是非常有用的,因?yàn)楝F(xiàn)在,如果這只鳥(niǎo)掉在地上,它看起來(lái)會(huì)是這樣的:

在這里插入圖片描述

看起來(lái)有點(diǎn)不自然。相反,我們想讓這只鳥(niǎo)從下面的東西中跳出來(lái):

在這里插入圖片描述

要在第二張圖片中創(chuàng)建彈跳效果,我們所要做的就是在項(xiàng)目區(qū)并選擇Create>Physics2D Material,說(shuō)出來(lái)鳥(niǎo)類(lèi)材料把它變成一個(gè)新的物理材料文件夾:

在這里插入圖片描述

一旦被選中,我們就可以修改Inspector:

在這里插入圖片描述

注:Bounciness值越大,鳥(niǎo)就越會(huì)反彈。

最后,我們可以再次選擇鳥(niǎo),然后拖動(dòng)鳥(niǎo)類(lèi)材料從項(xiàng)目區(qū)進(jìn)入Collider Material插槽:

在這里插入圖片描述

這只鳥(niǎo)也應(yīng)該四處走動(dòng)。剛體負(fù)責(zé)物體的重力、速度和其他使物體運(yùn)動(dòng)的力。根據(jù)經(jīng)驗(yàn)法則,在物理世界里,所有應(yīng)該移動(dòng)的東西都需要一個(gè)剛體.:

在這里插入圖片描述

注意:我們?cè)O(shè)置了Gravity Scale到4因?yàn)樗茏岠B(niǎo)飛得更快。

如果我們按下Play現(xiàn)在我們可以看到鳥(niǎo)從地上掉下來(lái)并彈跳起來(lái):

在這里插入圖片描述

我們的鳥(niǎo)類(lèi)物理已經(jīng)完成了,但是有一個(gè)小的調(diào)整是我們必須在這里進(jìn)行的?,F(xiàn)在,如果我們?cè)趶椆猩傻脑?,由于它的剛體引力,它會(huì)立即墜落到地面。我們只希望用戶(hù)一開(kāi)火,鳥(niǎo)就會(huì)受到重力的影響,所以讓我們現(xiàn)在啟用Is Kinematic,然后在腳本中禁用它:

在這里插入圖片描述

現(xiàn)在,剛體是運(yùn)動(dòng)學(xué)的,這意味著它不受重力或速度的影響,因此不會(huì)立即墜落。

注意:為了更清楚地說(shuō)明這一點(diǎn),任何像英雄、汽車(chē)或鳥(niǎo)之類(lèi)的東西都應(yīng)該有一個(gè)剛體,它是運(yùn)動(dòng)學(xué)的。我們只使能只要鳥(niǎo)還在彈弓里就能運(yùn)動(dòng)。

鳥(niǎo)預(yù)制體
如前所述,這只鳥(niǎo)從一開(kāi)始就不應(yīng)該出現(xiàn)在場(chǎng)景中。相反,彈弓應(yīng)該在需要的時(shí)候生成出一只新的鳥(niǎo)。為了使彈弓能夠生成鳥(niǎo),我們必須創(chuàng)建一個(gè)預(yù)制件 (換句話說(shuō),我們必須在我們的項(xiàng)目區(qū)有鳥(niǎo)的資源).

要?jiǎng)?chuàng)建預(yù)制件,我們所要做的就是在hierarchy面板,將物體拖入到項(xiàng)目區(qū)的Prefabs文件夾中:

在這里插入圖片描述

現(xiàn)在,我們可以在任何時(shí)候?qū)ⅧB(niǎo)加載到場(chǎng)景中,這意味著我們現(xiàn)在也可以從Hierarchy中刪除這個(gè)對(duì)象:

在這里插入圖片描述

生成鳥(niǎo)
讓我們將預(yù)制體bird拖到到我們的Spawn.cs的腳本中的BirdPrefab插槽中:

在這里插入圖片描述

如果我們按下Play現(xiàn)在我們可以看到彈弓是如何生出一只鳥(niǎo)的:

在這里插入圖片描述

拉and釋放腳本
用戶(hù)應(yīng)該能夠把鳥(niǎo)在彈弓周?chē)缓筢尫潘员惆阉湎蛩M姆较颉?/p>

我們將創(chuàng)造一個(gè)新的C#腳本給它起個(gè)名字PullAndRelease :

using UnityEngine;
using System.Collections;

public class PullAndRelease : MonoBehaviour {

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
}
用戶(hù)將能夠拖動(dòng)鳥(niǎo)繞一個(gè)圓圈。每個(gè)圓都需要一個(gè)中心,在我們的例子中,它是鳥(niǎo)的生成位置,所以讓我們確保將它保存在一個(gè)變量中:
using UnityEngine;
using System.Collections;

public class PullAndRelease : MonoBehaviour {
    // The default Position
    Vector2 startPos;

    // Use this for initialization
    void Start () {
        startPos = transform.position;
    }
}
*注意:我們還刪除了更新函數(shù)因?yàn)槲覀儾恍枰?/pre>

好的,為了讓用戶(hù)把鳥(niǎo)拖曳成一個(gè)圓圈,我們必須找出這只鳥(niǎo)是否被點(diǎn)擊了。(確切地說(shuō):拖著)…我們還需要知道用戶(hù)是否釋放了鼠標(biāo),在這種情況下,我們必須在我們目標(biāo)方向發(fā)射鳥(niǎo)。

當(dāng)然,如果沒(méi)有這方面的功能,那就不是Unity了。Unity自動(dòng)調(diào)用Onmouseup和OnmouseDrag函數(shù),當(dāng)我們用鼠標(biāo)拖動(dòng)游戲?qū)ο蠡螂S后釋放鼠標(biāo)時(shí):

*注:鼠標(biāo)拖動(dòng),意思是用戶(hù)在GameObject上按住鼠標(biāo)按鈕,然后移動(dòng)鼠標(biāo)。

移動(dòng)鳥(niǎo)真的很容易。我們所要做的就是將當(dāng)前的鼠標(biāo)位置轉(zhuǎn)換到游戲世界的某個(gè)點(diǎn),然后將鳥(niǎo)移到那里。當(dāng)然,只有在一定半徑內(nèi):

void OnMouseDrag() {    // Convert mouse position to world position    Vector2 p= Camera.main.ScreenToWorldPoint(Input.mousePosition);    // Keep it in a certain radius    float radius = 1.8f;    Vector2 dir = p - startPos;    if (dir.sqrMagnitude > radius)        dir = dir.normalized * radius;    // Set the Position    transform.position = startPos + dir;}

*注意:我們可以使用ScreenToWorldPoint獲取到手指點(diǎn)擊的位置,但是這個(gè)位置是不固定的,在找到手指點(diǎn)擊的位置p之后,我們只需要計(jì)算從startPos到p的距離,如果這個(gè)距離太長(zhǎng)dir.sqrMagnitude > radius,就讓這個(gè)位置等于一個(gè)最大值dir = dir.normalized * radius

如果我們按下Play然后我們可以把鳥(niǎo)繞個(gè)圈:

在這里插入圖片描述

把鳥(niǎo)射向一個(gè)方向也同樣容易。我們可以用我們的Onmouseup函數(shù)來(lái)知道鼠標(biāo)何時(shí)釋放。然后,我們將計(jì)算出從鳥(niǎo)到startPos然后使用rigidbody的AddForce在那里啟動(dòng)它的功能:

// The Force added upon releasepublic float force = 1300;void OnMouseUp() {    // Disable isKinematic    GetComponent<Rigidbody2D>().isKinematic = false;    // Add the Force    Vector2 dir = startPos - (Vector2)transform.position;    GetComponent<Rigidbody2D>().AddForce(dir * force);    // Remove the Script (not the gameObject)    Destroy(this);}

*注意:如前所述,我們也將禁用運(yùn)動(dòng)學(xué)等使剛體再次受到重力和速度的影響。我們只需將當(dāng)前位置減去startPos…最后,我們刪除這個(gè)對(duì)象,這樣它就不能再被發(fā)射了。

如果我們按下Play然后我們就可以拉著這只鳥(niǎo)開(kāi)火了:

在這里插入圖片描述

Feather Particle Effect羽毛的粒子效果
讓我們通過(guò)增加鳥(niǎo)的碰撞效果來(lái)使游戲更加流暢。一旦它第一次落地,它就應(yīng)該像這樣在自己周?chē)S意地長(zhǎng)出羽毛:

在這里插入圖片描述

當(dāng)我們需要隨機(jī)粒子產(chǎn)生、旋轉(zhuǎn)和向某個(gè)方向移動(dòng)時(shí),就會(huì)使用粒子系統(tǒng)。粒子系統(tǒng)的一個(gè)簡(jiǎn)單的例子是煙霧,它產(chǎn)生灰色紋理,然后以錐狀向上移動(dòng)。

我們將修改我們的粒子系統(tǒng),使其不是使粒子向上飛,而是使它們飛向四面八方。我們還將修改一些更具體的東西,如大小,速度和旋轉(zhuǎn)。我們的羽毛沒(méi)有正確或錯(cuò)誤的粒子系統(tǒng),所以你可以隨意使用它,直到它看起來(lái)像你想讓它看起來(lái)那樣。以下是我們得出的結(jié)論:

在這里插入圖片描述

這是我們用來(lái)做這件事的圖像:

在這里插入圖片描述

*注意:右擊圖像,選擇另存為.。并將其保存在項(xiàng)目的Assets/Sprites文件夾。

導(dǎo)入設(shè)置:

在這里插入圖片描述

之后,我們可以從項(xiàng)目區(qū)進(jìn)入我們粒子系統(tǒng)所以它使用圖像對(duì)所有的粒子。

現(xiàn)在我們可以將場(chǎng)景中的羽毛對(duì)象拖入到我們項(xiàng)目區(qū)的Prefabs文件夾,做成一個(gè)預(yù)制體:

在這里插入圖片描述

然后我們可以在Hierarchy中刪除羽毛游戲?qū)ο?/p>

最后一件事是給我們的鳥(niǎo)添加一個(gè)腳本,這樣羽毛粒子系統(tǒng)就會(huì)在發(fā)生碰撞時(shí)產(chǎn)生。讓我們?cè)陧?xiàng)目區(qū)然后創(chuàng)建新腳本…我們給它起個(gè)名字CollisionSpawnOnce。我們也會(huì)把它移到我們的Sprits文件夾,然后雙擊它以打開(kāi)它:

using UnityEngine;
using System.Collections;

public class CollisionSpawnOnce : MonoBehaviour {

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
}
我們不需要啟動(dòng)或更新函數(shù)。相反,我們將使用OnCollisionEnter2D函數(shù)和effect公共游戲?qū)ο髴?yīng)生成的預(yù)制件的變量:
using UnityEngine;
using System.Collections;

public class CollisionSpawnOnce : MonoBehaviour {
    // Whatever should be spawned (Particles etc.)
    public GameObject effect;

    void OnCollisionEnter2D(Collision2D coll) {
        // Spawn Effect, then remove Script
        Instantiate(effect,transform.position,Quaternion.identity);
        Destroy(this);
    }
}
*注意:為了確保只產(chǎn)生一次效果,我們將從Destroy(this)(這只會(huì)關(guān)閉腳本,而不是整只鳥(niǎo))。

保存腳本后,我們可以看到Effect插槽…現(xiàn)在我們可以拖著羽毛粒子系統(tǒng)預(yù)制件項(xiàng)目區(qū)進(jìn)入Effect插槽:

在這里插入圖片描述

如果我們按下Play然后把這只鳥(niǎo)發(fā)射到地上,然后我們就可以看到它周?chē)挠鹈谏桑?/p>

在這里插入圖片描述

路徑
我們還會(huì)給我們的鳥(niǎo)添加另一個(gè)效果,讓它看起來(lái)更流暢:一條白點(diǎn)的軌跡,顯示鳥(niǎo)的軌跡:

在這里插入圖片描述

首先,我們需要一些大小不同的跟蹤圖像:

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

我們會(huì)用同樣的導(dǎo)入設(shè)置對(duì)于每一幅圖像:

在這里插入圖片描述

我們希望能夠在我們想要的任何時(shí)候產(chǎn)生軌跡部分,這意味著我們將需要三個(gè)預(yù)制件。因此,讓我們選擇三個(gè)圖像并將其拖到場(chǎng)景中,然后拖回到Prefabs文件夾。直到我們有三個(gè)預(yù)制體:

在這里插入圖片描述

現(xiàn)在我們只需要一個(gè)腳本來(lái)生成一個(gè)又一個(gè)的TRAIL元素,大約每秒鐘一次。讓我們創(chuàng)建一個(gè)新的C#腳本給它起個(gè)名字Trail :

using UnityEngine;
using System.Collections;

public class Trail : MonoBehaviour {

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
}
我們可以移除更新因?yàn)槲覀儾恍枰?。讓我們添加一個(gè)public GameObject[]保存所有跟蹤元素的變量。我們將使用Array,這意味著它不僅僅是一個(gè)GameObject:
using UnityEngine;
using System.Collections;

public class Trail : MonoBehaviour {

    // Trail Prefabs
    public GameObject[] trails;

    // Use this for initialization
    void Start () {

    }
}
我們還需要一個(gè)函數(shù)來(lái)生成下一條線索。例如,它應(yīng)該產(chǎn)生第一個(gè)TRAIL元素,然后下一次應(yīng)該生成第二個(gè),然后是第三個(gè),然后是第一個(gè)。這可以通過(guò)使用實(shí)例化有一個(gè)額外的計(jì)數(shù)器變量:
using UnityEngine;
using System.Collections;

public class Trail : MonoBehaviour {

    // Trail Prefabs
    public GameObject[] trails;
    int next = 0;

    // Use this for initialization
    void Start () {

    }

    void spawnTrail() {
        Instantiate(trails[next], transform.position, Quaternion.identity);
        next = (next+1) % trails.Length;
    }
}
我們將其設(shè)置為0,這意味著trails spawnTrail中的第一個(gè)元素被調(diào)用。然后使用next+1來(lái)增加next。為了保持它在trails數(shù)組的范圍內(nèi),我們還將使用% trails.Length,它使用模(%)運(yùn)算。對(duì)于那些不了解模的人,這里有一個(gè)更明顯的版本:
void spawnTrail() {
    Instantiate(trails[next], transform.position, Quaternion.identity);
    next = next + 1;
    if (next == trails.Length) next = 0;
}
現(xiàn)在我們有了一個(gè)生成軌跡函數(shù),我們可以使用它生成一個(gè)新的trail 元素通過(guò)使用InvokeRepeting函數(shù)100 ms生成一個(gè):
using UnityEngine;
using System.Collections;

public class Trail : MonoBehaviour {

    // Trail Prefabs
    public GameObject[] trails;
    int next = 0;

    // Use this for initialization
    void Start () {
        // Spawn a new Trail every 100 ms
        InvokeRepeating("spawnTrail", 0.1f, 0.1f);
    }

    void spawnTrail() {
        Instantiate(trails[next], transform.position, Quaternion.identity);
        next = (next+1) % trails.Length;
    }
}
現(xiàn)在,小徑元素會(huì)一直生成,甚至當(dāng)鳥(niǎo)不飛的時(shí)候也是如此。讓我們添加一個(gè)小小的修改,只在鳥(niǎo)飛得足夠快的情況下才會(huì)產(chǎn)生軌跡:
void spawnTrail() {
    // Spawn Trail if moving fast enough
    if (GetComponent<Rigidbody2D>().velocity.sqrMagnitude > 25) {
        Instantiate(trails[next], transform.position, Quaternion.identity);
        next = (next+1) % trails.Length;
    }
}
好的,讓我們保存腳本。在這里,我們將從我們的三條小徑預(yù)制體中拖到插槽中:

在這里插入圖片描述

如果我們按下Play然后我們就可以看到這只鳥(niǎo)射擊后的蹤跡:

在這里插入圖片描述

7.木片

讓我們添加一些結(jié)構(gòu),如石頭,冰和木材,我們的Unity2D憤怒的小鳥(niǎo)游戲更加豐富。

我們先畫(huà)一塊木片:

在這里插入圖片描述

注意:右擊圖像,選擇另存為。并將其保存在項(xiàng)目的Assetes/Sprits文件夾。

這里是導(dǎo)入設(shè)置:

在這里插入圖片描述

現(xiàn)在我們可以把它拖到場(chǎng)景把它放在地上的某個(gè)地方:

在這里插入圖片描述

木片應(yīng)該是物理世界的一部分,所以我們將一如既往地在添加Box Collider 2D組件:

在這里插入圖片描述

木片也應(yīng)該能夠四處移動(dòng)?,F(xiàn)在它不會(huì)自己移動(dòng),但是如果鳥(niǎo)飛進(jìn)它,它就會(huì)移動(dòng)。它也應(yīng)該受到重力的影響,所以我們需要的是剛體…我們可以通過(guò)選擇添加組件->物理二維->Rigidbody 2D…我們也會(huì)增加Mass到4所以它更重了一點(diǎn):

在這里插入圖片描述

現(xiàn)在我們有一塊木頭,它是物理世界的一部分!

對(duì)于這個(gè)略有不同的木片,我們將重復(fù)相同的工作流程:

在這里插入圖片描述

這是我們的游戲如何看待添加第二塊木材和旋轉(zhuǎn)第一個(gè)90°:

在這里插入圖片描述

8.石頭

為了在我們的游戲中有幾種不同的結(jié)構(gòu),我們還將添加兩種不同類(lèi)型的石頭:

在這里插入圖片描述

在這里插入圖片描述

操作流程和以前一樣,這次我們將Mass設(shè)置為10:

在這里插入圖片描述

下面是我們的游戲中有一些石頭的樣子:

在這里插入圖片描述

注:我們?cè)俅螌?shí)現(xiàn)了一些體面的外觀與基本的形狀,只有少數(shù)顏色和抖動(dòng)。

9.冰

冰的圖片
我們將為我們的游戲增加一個(gè)結(jié)構(gòu):冰。不過(guò),這一次會(huì)更有趣一些。

像往常一樣,我們首先畫(huà)一塊冰:

在這里插入圖片描述

這個(gè)導(dǎo)入設(shè)置與以往相同:

在這里插入圖片描述

冰物理
添加 Boxcollider2D組件 剛體組件:

在這里插入圖片描述

冰應(yīng)該很滑,所以讓我們右擊項(xiàng)目區(qū)并選擇創(chuàng)造->物理二維材料給它起個(gè)名字冰IceMaterial:

在這里插入圖片描述

設(shè)置參數(shù):

在這里插入圖片描述

之后,我們可以在Hierarchy面板中選擇冰然后將IceMaterial從項(xiàng)目區(qū)拖入到BoxCollider2D>Material插槽:

在這里插入圖片描述

撞擊時(shí)摧毀冰
如果被足夠的力量撞擊,我們也希望冰層被摧毀,因?yàn)檫@就是冰的自然作用。我們添加腳本BreakOnImpact.cs腳本:

using UnityEngine;
using System.Collections;

public class BreakOnImpact : MonoBehaviour {

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
}
我們不需要啟動(dòng)或者更新函數(shù),所以讓我們移除這兩個(gè)函數(shù)。我們需要一種方法來(lái)估計(jì)碰撞的力量。我們將保持簡(jiǎn)單,并將速度與質(zhì)量相乘:
float collisionForce(Collision2D coll) {
    // Estimate a collision's force (speed * mass)
    float speed = coll.relativeVelocity.sqrMagnitude;
    if (coll.collider.GetComponent<Rigidbody2D>())
        return speed * coll.collider.GetComponent<Rigidbody2D>().mass;
    return speed;
}
*注:Collision2D繼承OnCollisionEnter2D功能,我們將獲取一個(gè)估計(jì)碰撞的力量,它包含方向與速度相乘。如果我們只關(guān)心速度,那么我們可以使用coll.relativeVelocity.sqrMagnitude…現(xiàn)在,如果造成碰撞的對(duì)象有剛體然后我們把速度乘以剛體的質(zhì)量…否則我們只返回速度。

好了,現(xiàn)在我們可以用OnCollisionEnter2D函數(shù)以獲得有關(guān)碰撞的通知。然后,我們將比較碰撞的力量和一個(gè)可配置的變量。如果它比力大,那么冰就會(huì)破裂:

using UnityEngine;
using System.Collections;

public class BreakOnImpact : MonoBehaviour {
    public float forceNeeded = 1000;

    float collisionForce(Collision2D coll) {
        // Estimate a collision's force (speed * mass)
        float speed = coll.relativeVelocity.sqrMagnitude;
        if (coll.collider.GetComponent<Rigidbody2D>())
            return speed * coll.collider.GetComponent<Rigidbody2D>().mass;
        return speed;
    }

    void OnCollisionEnter2D(Collision2D coll) {
        if (collisionForce(coll) >= forceNeeded)
            Destroy(gameObject);
    }
}
如果我們保存腳本,請(qǐng)按Play把鳥(niǎo)碰撞冰層,然后它就會(huì)破裂:

在這里插入圖片描述

現(xiàn)在,我們可以花幾分鐘來(lái)復(fù)制這些結(jié)構(gòu),并將它們放在一起,這樣我們就可以在它們之間添加豬了:

在這里插入圖片描述

10.綠豬

鳥(niǎo)兒想要消滅所有的豬,所以讓我們把一些豬加入到我們的游戲中,這樣鳥(niǎo)兒就不會(huì)覺(jué)得無(wú)聊了。

我們首先畫(huà)一個(gè):

在這里插入圖片描述

導(dǎo)入設(shè)置:

在這里插入圖片描述

添加碰撞器和剛體:

在這里插入圖片描述

如果有足夠大的力量襲擊豬,豬就會(huì)死。幸運(yùn)的是,我們已經(jīng)有了一個(gè)腳本。給我們的pig物體添加腳本BreakOnImpact.cs,并且設(shè)置Force Needed的值:

在這里插入圖片描述

*注意:能夠重用這樣的腳本是基于組件的開(kāi)發(fā)。

現(xiàn)在我們可以復(fù)制這頭豬并把它移到一些結(jié)構(gòu)之間:

在這里插入圖片描述

如果我們按下Play然后我們就可以試著消滅豬了:

在這里插入圖片描述

11.橡膠

我們將為我們的游戲添加最后一個(gè)功能:彈弓橡膠,所以拖拽和釋放鳥(niǎo)看起來(lái)要好得多:

在這里插入圖片描述

我們首先畫(huà)一半的橡膠,這幾乎只是一條粗線:

在這里插入圖片描述

這里是導(dǎo)入設(shè)置:

在這里插入圖片描述

*注意:這次我們?cè)O(shè)置了Pivot到右(邊),正確的讓一些旋轉(zhuǎn)變得更容易。

現(xiàn)在我們可以從項(xiàng)目區(qū)進(jìn)入場(chǎng)景兩次,說(shuō)出其中一個(gè)左橡膠,另一個(gè)右橡膠把它們放在彈弓的上部:

在這里插入圖片描述

我們要確保左邊的那個(gè)總是畫(huà)出來(lái)的。后面彈弓和右彈弓總是被拉進(jìn)去的。前面其中的一部分。我們可以再加兩個(gè)分類(lèi)層對(duì)于我們的游戲,但我們將保持簡(jiǎn)單,只需更改層序到-1左邊的橡膠和1右邊的橡膠:

在這里插入圖片描述

在這里插入圖片描述

現(xiàn)在橡膠看起來(lái)就像在外彈弓:

在這里插入圖片描述

在開(kāi)始編寫(xiě)腳本之前,讓我們?cè)贖ierarchy然后將這兩個(gè)對(duì)象設(shè)置為slingshot的子對(duì)象:

在這里插入圖片描述

*注意:每當(dāng)我們移動(dòng)彈弓時(shí),橡膠部件就會(huì)隨之移動(dòng)。

讓我們創(chuàng)建一個(gè)新的C#腳本給它起個(gè)名字Rubber:

using UnityEngine;
using System.Collections;

public class Rubber : MonoBehaviour {

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
}
這個(gè)腳本的目的是讓兩個(gè)橡膠部分跟隨鳥(niǎo),直到它離開(kāi)生成鳥(niǎo)的觸發(fā)圈。

我們需要兩個(gè)變量leftRubber 和rightRubber,讓我們?cè)谝院笾付ㄏ鹉z。我們不需要啟動(dòng)或者更新函數(shù),讓我們刪除掉它們:

using UnityEngine;
using System.Collections;

public class Rubber : MonoBehaviour {
    // The Rubber objects
    public Transform leftRubber;
    public Transform rightRubber;
}
現(xiàn)在,有一些稍微復(fù)雜一些的功能。我們將需要一個(gè)功能,定位橡膠在彈弓和鳥(niǎo)的位置,我們必須先將橡膠旋轉(zhuǎn)到鳥(niǎo)的方向,然后根據(jù)鳥(niǎo)的距離使橡膠變成或變短:
void adjustRubber(Transform bird, Transform rubber) {
    // Rotation
    Vector2 dir = rubber.position - bird.position;
    float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
    rubber.rotation = Quaternion.AngleAxis(angle, Vector3.forward);

    // Length
    float dist = Vector3.Distance(bird.position, rubber.position);
    dist += bird.GetComponent<Collider2D>().bounds.extents.x;
    rubber.localScale = new Vector2(dist, 1);
}
注意:首先我們計(jì)算從鳥(niǎo)到橡膠的距離,然后計(jì)算這個(gè)方向的角度。然后我們,通過(guò)Quaternion.AngleAxis(angle, Vector3.forward)將橡膠旋轉(zhuǎn)到這個(gè)角度。最后,我們計(jì)算從鳥(niǎo)到橡膠的距離,之后,我們將橡膠的縮放設(shè)置為這個(gè)距離加上碰撞器的x的長(zhǎng)度既dist += bird.GetComponent().bounds.extents.x

這個(gè)OnTriggerStay2D功能將通知我們,每當(dāng)鳥(niǎo)改變它的位置時(shí),它還在彈弓。我們可以使用這個(gè)函數(shù)來(lái)調(diào)整左右橡皮筋:

using UnityEngine;
using System.Collections;

public class Rubber : MonoBehaviour {
    // The Rubber objects
    public Transform leftRubber;
    public Transform rightRubber;

    void adjustRubber(Transform bird, Transform rubber) {
        // Rotation
        Vector2 dir = rubber.position - bird.position;
        float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
        rubber.rotation = Quaternion.AngleAxis(angle, Vector3.forward);

        // Length
        float dist = Vector3.Distance(bird.position, rubber.position);
        dist += bird.GetComponent<Collider2D>().bounds.extents.x;
        rubber.localScale = new Vector2(dist, 1);
    }

    void OnTriggerStay2D(Collider2D coll) {
        // Stretch the Rubber between bird and slingshot
        adjustRubber(coll.transform, leftRubber);
        adjustRubber(coll.transform, rightRubber);
    }
}
快好了。我們將再增加一個(gè)離開(kāi)時(shí)候觸發(fā)的事件,使橡皮筋在發(fā)射后變短:
void OnTriggerExit2D(Collider2D coll) {
    // Make the Rubber shorter
    leftRubber.localScale = new Vector2(0, 1);
    rightRubber.localScale = new Vector2(0, 1);
}
現(xiàn)在,我們可以通過(guò)首先選擇彈弓對(duì)象中的游戲?qū)ο?。層次性然后點(diǎn)擊添加組件->Scitps->Rubber…我們亦會(huì)把這兩個(gè)橡膠拖到相應(yīng)的槽內(nèi):

在這里插入圖片描述

如果我們按下Play現(xiàn)在我們可以看到小鳥(niǎo)和彈弓之間的橡皮筋:

在這里插入圖片描述

當(dāng)然,現(xiàn)在我們也可以玩一輪憤怒的小鳥(niǎo)了:

在這里插入圖片描述

總結(jié)

到這里本篇文章就結(jié)束了,我們剛剛創(chuàng)建了一個(gè)小游戲憤怒的小鳥(niǎo)翻版,使用簡(jiǎn)單的形狀與顏色來(lái)達(dá)到一個(gè)良好的效果,廣泛的使用了Unity的2D物理引擎,添加了許多的效果

相關(guān)文章

  • c# 如何使用 My 命名空間

    c# 如何使用 My 命名空間

    這篇文章主要介紹了c# 如何使用 My 命名空間,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下
    2020-10-10
  • C#監(jiān)控文件夾并自動(dòng)給圖片文件打水印的方法

    C#監(jiān)控文件夾并自動(dòng)給圖片文件打水印的方法

    這篇文章主要介紹了C#監(jiān)控文件夾并自動(dòng)給圖片文件打水印的方法,涉及C#針對(duì)文件夾及圖片操作的相關(guān)技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-05-05
  • 深入解析C#中的交錯(cuò)數(shù)組與隱式類(lèi)型的數(shù)組

    深入解析C#中的交錯(cuò)數(shù)組與隱式類(lèi)型的數(shù)組

    這篇文章主要介紹了深入解析C#中的交錯(cuò)數(shù)組與隱式類(lèi)型的數(shù)組,隱式類(lèi)型的數(shù)組通常與匿名類(lèi)型以及對(duì)象初始值設(shè)定項(xiàng)和集合初始值設(shè)定項(xiàng)一起使用,需要的朋友可以參考下
    2016-01-01
  • 在C#中如何使用Dapper詳解(譯)

    在C#中如何使用Dapper詳解(譯)

    這篇文章主要給大家介紹了關(guān)于在C#中如何使用Dapper的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起看看吧
    2018-09-09
  • Unity快速生成常用文件夾的方法

    Unity快速生成常用文件夾的方法

    這篇文章主要介紹了Unity快速生成常用文件夾的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-09-09
  • C#圖表算法之有向圖

    C#圖表算法之有向圖

    這篇文章介紹了C#圖表算法之有向圖,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-04-04
  • C#圖像識(shí)別 微信跳一跳機(jī)器人

    C#圖像識(shí)別 微信跳一跳機(jī)器人

    這篇文章主要為大家詳細(xì)介紹了C#圖像識(shí)別,微信跳一跳機(jī)器人,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • c#與mysql的連接

    c#與mysql的連接

    c#與mysql的連接...
    2007-03-03
  • C#實(shí)現(xiàn)聊天消息渲染與圖文混排詳解

    C#實(shí)現(xiàn)聊天消息渲染與圖文混排詳解

    在實(shí)現(xiàn)聊天軟件時(shí),渲染文字表情圖文混排是一項(xiàng)非常繁瑣的工作,再加上還要支持GIF動(dòng)圖、引用消息、撤回消息、名片等不同樣式的消息渲染時(shí),就更加麻煩了。本文就來(lái)和大家分享一下具體實(shí)現(xiàn)方法,希望對(duì)大家有所幫助
    2023-02-02
  • C# 并發(fā)控制框架之單線程環(huán)境下實(shí)現(xiàn)每秒百萬(wàn)級(jí)調(diào)度

    C# 并發(fā)控制框架之單線程環(huán)境下實(shí)現(xiàn)每秒百萬(wàn)級(jí)調(diào)度

    本文介紹了一款專(zhuān)為工業(yè)自動(dòng)化及機(jī)器視覺(jué)開(kāi)發(fā)的C#并發(fā)流程控制框架,通過(guò)模仿Go語(yǔ)言并發(fā)模式設(shè)計(jì),支持高頻調(diào)度及復(fù)雜任務(wù)處理,已在多個(gè)項(xiàng)目中驗(yàn)證其穩(wěn)定性和可靠性
    2024-10-10

最新評(píng)論