最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

Unity快速上手系列之2:2D物理彈球

2018-09-05 18:05 作者:皮皮關(guān)做游戲  | 我要投稿

作者:四五二十


大家好。

跳一跳為開端,微信小游戲從今年年初起以迅雷不及掩耳盜鈴兒響叮當(dāng)之勢(shì)席卷了用戶的手機(jī)。從創(chuàng)意小游戲,到頁游遺風(fēng)的掛機(jī)游戲,一時(shí)間百花齊放。
當(dāng)然,前者說是創(chuàng)意,其實(shí)絕大部分也就是直接把其他平臺(tái)上的游戲模式搬到H5上而已,例如經(jīng)典的三維彈球。
而作為物理引擎的代表作品,實(shí)現(xiàn)一款三維彈球作品對(duì)初學(xué)者的鍛煉還是挺大的。這也是寫這篇小文的主要目的。

制作此游戲分為兩個(gè)大的步驟,一是場(chǎng)景搭建,二是腳本編寫。下面我們就來一起逐步完成這款小游戲。

場(chǎng)景搭建:游戲?qū)儆?D游戲,所以場(chǎng)景我們用2D精靈(Sprite)來搭建


一.砌墻


首先搭建一圈2D碰撞器作圍墻,限制小球活動(dòng)范圍:

所有的墻都要在2D碰撞器內(nèi)添加拖入彈性物理材質(zhì),上下墻不添加


二.鋪路


在小球外部活動(dòng)范圍內(nèi)搭建觸發(fā)器,之后將在觸發(fā)器中獲得尋路效果:

可創(chuàng)建一個(gè)空物體進(jìn)行管理

三,槍口


槍口(Muzzle)用來定位小球發(fā)射的地方,槍口有個(gè)子物體閥門(Valve),作用為阻擋已發(fā)射的小球被彈回槍口:

槍口需要添加LineRenderer組件,用來繪制瞄準(zhǔn)線,閥門需要添加2D碰撞器


四.分?jǐn)?shù)顯示

創(chuàng)建一個(gè)空物體Score,它的子物體CurrentScore才是用來顯示分?jǐn)?shù)的Text:

五.小球管理


創(chuàng)建一個(gè)空物體Balls來管理所有的小球,使用2D精靈創(chuàng)建一個(gè)小球

六.關(guān)卡設(shè)置


在場(chǎng)景內(nèi)一共搭建9*6個(gè)小格子,每個(gè)小格子都用來隨機(jī)生成敵人,實(shí)行分層管理,每層6個(gè),共9層:

注意:綠色小方框只是為了教程更加直觀特意加的,實(shí)際開發(fā)時(shí)請(qǐng)移除,小格子并未添加除Transform以外的任何組件,因?yàn)樾「褡拥淖饔镁褪嵌ㄎ?游戲運(yùn)行時(shí)需要在該位置隨機(jī)生成敵人;

七.菜單欄


游戲結(jié)束時(shí)自動(dòng)彈出,游戲運(yùn)行中按”Esc”鍵也可調(diào)用:

八,攝像機(jī)定位


由于整個(gè)場(chǎng)景都處于固定狀態(tài),所以將Canvas設(shè)為世界模式:

將攝像機(jī)改為正交模式

將固定在整個(gè)場(chǎng)景前:

九.預(yù)制件制作


創(chuàng)建若干個(gè)敵人(Enemy)預(yù)制件,添加上2D碰撞器和物理彈性材質(zhì)

創(chuàng)建道具(Stunt)預(yù)制件

變大道具BigStunt:碰到后球會(huì)變大
復(fù)制道具CopyStunt:碰到后增加一個(gè)小球


創(chuàng)建小球(Ball)預(yù)制件,當(dāng)碰到復(fù)制特效后創(chuàng)建


腳本編寫:腳本不多,加上2個(gè)狀態(tài)機(jī)也就11個(gè)

我們下面來一一介紹它們:


一.LevelCreate

腳本說明:隨機(jī)生成底層關(guān)卡的元素。


using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

/// <summary>

/// LevelPanel

/// </summary>

public class LevelCreate : MonoBehaviour

{

    //在編輯器中將當(dāng)前分?jǐn)?shù)ScoreText拖進(jìn)去

    public Text scoreText;

    //所有種類幾何體,在編輯器把所有幾何體預(yù)制件拖進(jìn)去

    public Transform[] Enemys;

    //所有種類道具,在編輯器把所有道具預(yù)制件拖進(jìn)去

    public Transform[] stunts;

 

    //物體生成器,決定格子里是否生成東西(幾率可自行設(shè)定)

    public Transform PaneFactory()

    {

        int chance = Random.Range(0, 4);

        if (chance < 3)          //75%不產(chǎn)生東西,

            return null;

        else                     //25%產(chǎn)生東西

            return PaneManage();

    }

    //決定格子里該生產(chǎn)什么東西

    Transform PaneManage()

    {

        int chance = Random.Range(0, 3);

        if (chance < 2)           //66%產(chǎn)生幾何體

            return CreateEnemy();

        else                      //33%產(chǎn)生道具

            return CreateStunt();

    }

    //隨機(jī)生成道具

    Transform CreateStunt()

    {

        //隨機(jī)產(chǎn)生一個(gè)道具數(shù)組索引

        int index = Random.Range(0, stunts.Length);

        //生成該索引處道具

        return Instantiate(stunts[index]);

    }

    //隨機(jī)生成敵人

    public Transform CreateEnemy()

    {

        //隨機(jī)產(chǎn)生一個(gè)幾何體數(shù)組索引

        int index = Random.Range(0, E*******ength);

        //生成該索引處幾何體

        Transform enemy = Instantiate(Enemys[index]);

        //給幾何體賦一個(gè)隨機(jī)顏色

        enemy.GetComponent<Renderer>().material.color = new Color(Random.value, Random.value, Random.value);

        //給幾何體一個(gè)隨機(jī)旋轉(zhuǎn)角度

        enemy.rotation = Quaternion.Euler(0, 0, Random.Range(0, 90));

        //獲取幾何體子物體數(shù)字的Transform組件

        Transform tf = enemy.GetComponentInChildren<Text>().transform;

        //子物體不旋轉(zhuǎn)

        tf.rotation = Quaternion.Euler(0, 0, 0);      

        //獲取當(dāng)前分?jǐn)?shù)

        int score = System.Convert.ToInt32(scoreText.text);      

        if (score < 100) //如果當(dāng)前分?jǐn)?shù)不超過100

            //幾何體數(shù)字在 1~9 之間隨機(jī)生成

            enemy.GetComponentInChildren<Text>().text = Random.Range(1, 10).ToString();

        else //當(dāng)前分?jǐn)?shù)超過100

            //幾何體數(shù)字在 1~當(dāng)前分?jǐn)?shù)/10 之間隨機(jī)生成

            enemy.GetComponentInChildren<Text>().text = Random.Range(1, score / 10).ToString();

        return enemy;

    }

}

 

.LevelState

腳本說明:關(guān)卡狀態(tài)機(jī),表示當(dāng)前游戲運(yùn)行狀態(tài)。

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

/// <summary>

/// 關(guān)卡運(yùn)行狀態(tài)

/// </summary>

public enum LevelState

{

    life,  //運(yùn)行中

    pause, //暫停

    die, //游戲結(jié)束

}

 


三.LevelMove

腳本說明:

1.關(guān)卡移動(dòng)方式,底層往上走一層,頂層回到最底層;

2.對(duì)頂層的物體進(jìn)行判斷,如果敵人到達(dá)頂層,游戲結(jié)束;

3.在最底層生成新的物體;

關(guān)卡運(yùn)動(dòng)方向


using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

/// <summary>

/// LevelPanel

/// </summary>

public class LevelMove : MonoBehaviour

{

    //需要做一個(gè)菜單,游戲死亡時(shí)彈出,在編輯器把死亡菜單拖進(jìn)來

    public GameObject deathPanel;

    //游戲初始狀態(tài)為存活

    public LevelState levelState = LevelState.life;

    //聲明一個(gè)關(guān)卡集合用來管理每層關(guān)卡

    List<Transform> lineList = new List<Transform>();

    LevelCreate levelcreate; //聲明創(chuàng)建物體的類

    private void Start()

    {

        levelcreate = GetComponent<LevelCreate>(); //獲取創(chuàng)建關(guān)卡類

        lineList = GetAllChild(transform); //獲取第一層子物體(關(guān)卡)添加進(jìn)關(guān)卡集合中  

        CreateLevel(); //游戲開始時(shí)創(chuàng)建一次底層的物體

    }

    private void Update()

    {

        //在游戲運(yùn)行時(shí)按Esc

        if (levelState == LevelState.life && Input.GetKeyDown(KeyCode.Escape))

        {

            levelState = LevelState.pause; //游戲狀態(tài)變?yōu)闀和?/span>

            deathPanel.SetActive(true); //啟用菜單

            Time.timeScale = 0; //游戲暫停

        }

        //在暫停狀態(tài)時(shí)按Esc

        else if (levelState == LevelState.pause && Input.GetKeyDown(KeyCode.Escape))

        {

            levelState = LevelState.life; //游戲狀態(tài)變?yōu)檫\(yùn)行

            deathPanel.SetActive(false); //禁用菜單

            Time.timeScale = 1; //游戲恢復(fù)

        }

    }

    List<Transform> GetAllChild(Transform fatherObj) //獲取所有第一層子物體

    {

        //聲明一個(gè)集合放第一層所有子物體

        List<Transform> sonList = new List<Transform>();

        int number = fatherObj.childCount; //獲取第一層子物體數(shù)量

        for (int i = 0; i < number; i++)

        {

            //將所有第一層子物體添加進(jìn)集合中

            sonList.Add(fatherObj.GetChild(i));

        }

        return sonList; //返回第一層子物體集合

    }

    void CreateLevel() //創(chuàng)建底層關(guān)卡

    {

        Transform last = lineList[lineList.Count - 1]; //獲取底層關(guān)卡,物體將從該層產(chǎn)生

        List<Transform> sonList = GetAllChild(last); //獲取底層所有小方格

        //生成一個(gè)幾何體(每次創(chuàng)建關(guān)卡至少有一個(gè)幾何體)

        Transform enemy = levelcreate.CreateEnemy();

        int index = Random.Range(0, last.childCount); //隨機(jī)定位一個(gè)格子

        enemy.position = last.GetChild(index).position; //將幾何體創(chuàng)建在該格子內(nèi)

        enemy.parent = last.GetChild(index); //幾何體作為該格子的子物體可隨關(guān)卡層移動(dòng)

 

        //然后在其它格子里隨機(jī)生成物體

        for (int i = 0; i < sonList.Count; i++)

        {

            if (i != index) //除了剛才已經(jīng)有敵人的格子外

            {

                //聲明一個(gè)變量接受生成的物體

                Transform obj = levelcreate.PaneFactory();

                if (obj != null) //如果成功生產(chǎn)出東西

                {

                    obj.position = sonList[i].position; //將該東西生產(chǎn)在此方格

                    obj.parent = sonList[i]; //作為該方格的子物體隨關(guān)卡層移動(dòng)

                }

            }

        }

    }

    //關(guān)卡往上走一層(第一層跳到最后)

    public void LevelGetUp()

    {

        Vector3 tempPos = lineList[lineList.Count - 1].position; //獲取最后層的坐標(biāo)

        //遍歷所有關(guān)卡層

        for (int i = lineList.Count - 1; i >= 0; i--)

        {

            if (i == 0) //如果是頂層

                lineList[i].position = tempPos; //直接跳到底層

            else //如果是其它層

                lineList[i].position = lineList[i - 1].position; //移動(dòng)到自己上一層

        }

        DestroyStunt(); //銷毀頂層道具

        lineList.Add(lineList[0]); //將第一層添加到集合最后

        lineList.RemoveAt(0); //再移除第一層

        CreateLevel(); //創(chuàng)建一次關(guān)卡關(guān)卡

        if (Death()) //判斷是否死亡

        {

            levelState = LevelState.die; //狀態(tài)變?yōu)樗劳?/span>

            deathPanel.SetActive(true); //調(diào)用菜單

        }

    }

    void DestroyStunt() //銷毀頂層特技

    {

        //獲取該層所有子物體

        Transform[] lineSon = lineList[0].GetComponentsInChildren<Transform>();     

        for (int i = 0; i < lineSon.Length; i++) //遍歷所有子物體的標(biāo)簽

        {

            if (lineSon[i].tag == "Stunt") //如果是道具

            {

                Destroy(lineSon[i].gameObject); //銷毀該子物體

            }

        }

    }

    bool Death() //死亡判斷

    {

        //獲取頂層所有子物體

        Transform[] lineSon = lineList[0].GetComponentsInChildren<Transform>();

        for (int i = 0; i < lineSon.Length; i++) //遍歷所有子物體的標(biāo)簽

        {

            if (lineSon[i].tag == "Enemy") //如果發(fā)現(xiàn)有幾何體

                return true; //直接游戲結(jié)束

        }

        return false; //如果一個(gè)都沒有,游戲繼續(xù)

    }

}

 

.BallState

腳本說明:小球狀態(tài)機(jī),小球會(huì)隨著游戲運(yùn)行改變狀態(tài),不同狀態(tài)的小球具有不同屬性。

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

/// <summary>

/// 小球狀態(tài)機(jī),不用掛在任何物體上

/// </summary>

public enum BallState

{  

    Ready, //準(zhǔn)備階段

    Battle, //戰(zhàn)斗階段

    Bore, //上膛階段

}

 

.BallMove

腳本說明:

1小球在創(chuàng)景中的交互;

2.發(fā)射前的小球處于準(zhǔn)備狀態(tài);

3.發(fā)射后的小球進(jìn)入轉(zhuǎn)斗狀態(tài),碰到敵人會(huì)加分,敵人會(huì)減血;

4.小球需要一個(gè)防卡住的方法;

小球卡住示意圖



using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

/// <summary>

/// 掛小球上

/// </summary>

public class BallMove : MonoBehaviour

{

    float timer; //計(jì)時(shí)用

    //初始狀態(tài)為準(zhǔn)備狀態(tài)

    public BallState state = BallState.Ready;

    //碰撞時(shí)調(diào)一次,用于打擊幾何體(敵人)

    private void OnCollisionEnter2D(Collision2D collision)

    {

       if (state == BallState.Battle) //如果在戰(zhàn)斗階段

       {

          GetComponent<Rigidbody2D>().gravityScale = 1; //碰到東西后重力為1

          if (collision.gameObject.tag == "Enemy") //如果碰到敵人   

          {

             //獲取敵人數(shù)字

             Text enemyNumber = collision.transform.GetChild(0).GetComponent<Text>();

             //獲取當(dāng)前分?jǐn)?shù)

             Text Score = GameObject.Find("ScoreText").GetComponent<Text>();

             if (tag == "BigBall") //如果自己是大球

             {

                //敵人數(shù)字-2

                enemyNumber.text = ((System.Convert.ToInt32(enemyNumber.text)) - 2).ToString();

                //當(dāng)前分?jǐn)?shù)+2

                Score.text = ((System.Convert.ToInt32(Score.text)) + 2).ToString();

             }

             else //如果自己是小球

             {

                //敵人數(shù)字-1

                enemyNumber.text = ((System.Convert.ToInt32(enemyNumber.text)) - 1).ToString();

                //當(dāng)前分?jǐn)?shù)+1

                Score.text = ((System.Convert.ToInt32(Score.text)) + 1).ToString();

             }

          }

       }

    }

    //碰撞時(shí)持續(xù)調(diào)用,防止小球被卡住

    private void OnCollisionStay2D(Collision2D collision)

    {

       if (collision.gameObject.tag == "Enemy") //如果碰撞的是敵人

       {

          timer += Time.deltaTime; //開始計(jì)時(shí)

          if (timer > 1) //一秒后還停留在那上面

          {

             switch (Random.Range(0, 4)) //隨機(jī)方向彈開

             {

                case 0:

                   GetComponent<Rigidbody2D>().AddForce(transform.up * 0.01f);

                   break;

                case 1:

                   GetComponent<Rigidbody2D>().AddForce(-transform.up * 0.01f);

                   break;

                case 2:

                   GetComponent<Rigidbody2D>().AddForce(transform.right * 0.01f);

                   break;

                case 3:

                   GetComponent<Rigidbody2D>().AddForce(-transform.up * 0.01f);

                   break;

             }

          }

       }

    }

    //離開碰撞時(shí)調(diào)一次

    private void OnCollisionExit2D(Collision2D collision)

    {

        timer = 0; //計(jì)時(shí)歸零

    }

    private void Update()

    {

        transform.Rotate(0, 0, 0.0001f); //物體處于非完全靜止?fàn)顟B(tài),持續(xù)碰撞才會(huì)生效

        switch (state)

        {

            case BallState.Bore: //上膛階段

                GetComponent<Rigidbody2D>().gravityScale = 0; //重力變?yōu)?/span>0

                break;

            case BallState.Ready: //準(zhǔn)備階段

                GetComponent<CircleCollider2D>().isTrigger = false; //關(guān)閉觸發(fā)

                GetComponent<Rigidbody2D>().Sleep(); //小球停止不動(dòng)

                break;

        }

    }

}

 

六.BallFindWay

腳本說明:

1.發(fā)射后的小球會(huì)尋路回到槍口,給每一個(gè)尋路碰撞器掛一個(gè);

2.碰到頂上的碰撞器后.小球會(huì)進(jìn)入上膛階段,直接回到槍口;


using System.Collections;

using System.Collections.Generic;

using UnityEngine;

/// <summary>

/// FindTheWays下的所有尋路碰撞器都掛一個(gè)

/// </summary>

public class BallFindWay : MonoBehaviour

{

    public Transform muzzle; //在編輯器把槍口拖進(jìn)去,我們需要槍口的坐標(biāo)

    public float boreSpeed=0.2f; //上膛速度

    private void OnTriggerStay2D(Collider2D ball) //觸發(fā)時(shí)持續(xù)調(diào)用

    {

        //獲取小球的剛體

        Rigidbody2D r2d = ball.GetComponent<Rigidbody2D>();

        switch (name) //根據(jù)尋路碰撞器的名字決定施加力的方向

        {

            case "LeftDown":

                r2d.AddForce(-transform.right * 0.002f);

                break;

            case "RightDown":

                r2d.AddForce(transform.right * 0.003f);

                break;

            case "Left":

            case "Right":

                r2d.AddForce(transform.up * 0.002f);

                break;

            case "Up":

                //啟動(dòng)協(xié)程尋路(上膛)  

                StartCoroutine(MoveToMuzzle(ball.transform, muzzle));

                //打開小球觸發(fā)器,使小球能越過槍口閥門

                ball.GetComponent<CircleCollider2D>().isTrigger = true;

                break;

        }

    }

    //使用協(xié)程尋路讓小球朝槍口處移動(dòng)

    public IEnumerator MoveToMuzzle(Transform ball, Transform muzzle)

    {

        ball.GetComponent<BallMove>().state = BallState.Bore; //小球狀態(tài)改為上膛狀態(tài)

        while (ball.GetComponent<BallMove>().state == BallState.Bore) //如果是上膛狀態(tài)

        {         

            //小球往槍口處尋路,完成上膛          

            ball.position = Vector3.MoveTowards(ball.position, muzzle.position, boreSpeed * Time.deltaTime);

            yield return new WaitForFixedUpdate(); //每次循環(huán)間隔1

            //如果小球位置和槍口位置接近

            if ((ball.position - muzzle.position).sqrMagnitude <= 0.001f)

            {

                ball.GetComponent<BallMove>().state = BallState.Ready; //小球進(jìn)入準(zhǔn)備階段

                ball.position = muzzle.position; //將小球定在槍口位置

            }

        }

    }

}



七.Aim

腳本說明:

1.把當(dāng)前小球依次發(fā)射出去,并將發(fā)射的小球變?yōu)閼?zhàn)斗狀態(tài);

2.小球發(fā)射方向是從槍口出發(fā),往鼠標(biāo)所在方向,顯示瞄準(zhǔn)線;

3.限制小球發(fā)射返回,不能往上發(fā)射,需要做兩個(gè)限制點(diǎn);

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

public class Aim : MonoBehaviour //掛槍口Muzzle

{

    public GameObject balls; //Balls拖進(jìn)去  

    Rigidbody2D[] allBall; //聲明一個(gè)數(shù)組用來管理所有小球

    LineRenderer aimLine; //聲明瞄準(zhǔn)線

    public Transform CriticalPointLeft; //把左邊界拖進(jìn)去

    public Transform CriticalPointRight; //把右邊界拖進(jìn)去

    public float shootingSpeed = 3.5f; //小球發(fā)射速度

    public GameObject levelPanel; //LevelPanel拖進(jìn)去

    bool levelStop; //判斷關(guān)卡是否已上升

    void Start()

    {

        Time.timeScale = 1; //游戲時(shí)間正常     

        allBall = balls.GetComponentsInChildren<Rigidbody2D>();//初始化(獲取當(dāng)前所有小球)

        aimLine = GetComponent<LineRenderer>(); //獲取槍口上的LineRenderer組件

    }

    void Update()

    {

        //當(dāng)游戲狀態(tài)為活著時(shí)

        if (levelPanel.GetComponent<LevelMove>().levelState == LevelState.life)

        {

            if (Homing()) //所有小球都進(jìn)入準(zhǔn)備狀態(tài)了

            {

                allBall = balls.GetComponentsInChildren<Rigidbody2D>(); //再次獲取所有小球

                if (levelStop) //關(guān)卡處于未上升狀態(tài)

                {

                    levelPanel.GetComponent<LevelMove>().LevelGetUp(); //調(diào)用關(guān)卡上升方法

                    levelStop = !levelStop; //關(guān)卡處于已上升狀態(tài)

                }

                else

                    AimLaunch(); //關(guān)卡上升完成后可進(jìn)行瞄準(zhǔn)發(fā)射

            }

        }

    }

    //判斷所有小球是否都進(jìn)入準(zhǔn)備狀態(tài)

    public bool Homing()

    {

        //發(fā)現(xiàn)任何小球不在準(zhǔn)備狀態(tài)都返回False

        for (int i = 0; i < allBall.Length; i++)

        {

            if (allBall[i].GetComponent<BallMove>().state != BallState.Ready)

                return false;

        }

        return true; //未發(fā)現(xiàn)不在準(zhǔn)備狀態(tài)的小球,返回True

    }

    void AimLaunch() //瞄準(zhǔn)發(fā)射

    {

        if (Input.GetMouseButtonDown(0)) //點(diǎn)擊鼠標(biāo)左鍵

        {

            aimLine.SetPosition(0, transform.position); //在槍口處生成瞄準(zhǔn)線起點(diǎn)

        }

        if (Input.GetMouseButton(0)) //按住鼠標(biāo)左鍵不放

        {

            //獲取鼠標(biāo)坐標(biāo)

            Vector3 v = Camera.main.ScreenToWorldPoint(Input.mousePosition);

            //限制瞄準(zhǔn)范圍

            v = DirectionRestriction(v, CriticalPointLeft, CriticalPointRight);

            //將被限制過的鼠標(biāo)坐標(biāo)實(shí)時(shí)給瞄準(zhǔn)線結(jié)束點(diǎn)

            aimLine.SetPosition(1, new Vector2(v.x, v.y));

        }

        if (Input.GetMouseButtonUp(0)) //抬起鼠標(biāo)左鍵

        {

            StartCoroutine(LineLaunch(transform.position)); //啟動(dòng)協(xié)程發(fā)射小球

            aimLine.SetPosition(1, transform.position); //讓結(jié)束點(diǎn)和起點(diǎn)重合(撤銷瞄準(zhǔn)線)

            levelStop = !levelStop; //關(guān)卡標(biāo)記為可上升狀態(tài)

        }

    }

  

    IEnumerator LineLaunch(Vector3 muzzlePos) //用協(xié)程排隊(duì)發(fā)射小球

    {

        Vector3 pos1 = aimLine.GetPosition(1);//獲取瞄準(zhǔn)線結(jié)束點(diǎn)坐標(biāo)

        Vector3 directionAttack = (pos1 - muzzlePos).normalized;//獲取瞄準(zhǔn)結(jié)束點(diǎn)與槍口的方向向量

        for (int i = 0; i < allBall.Length; i++) //挨個(gè)發(fā)射小球

        {

            //被發(fā)射的小球變?yōu)閼?zhàn)斗狀態(tài)

            allBall[i].GetComponent<BallMove>().state = BallState.Battle;

            //球往瞄準(zhǔn)結(jié)束點(diǎn)方向?qū)ぢ芬苿?dòng) 

            allBall[i].AddForce(directionAttack * shootingSpeed * Time.deltaTime);      

            yield return new WaitForSeconds(0.1f); //每隔0.1秒發(fā)射一個(gè)

        }

    }

    //限定槍口瞄準(zhǔn)方向

    Vector3 DirectionRestriction(Vector3 v, Transform left, Transform right)

    {

        //最左不能左過左邊界

        if (v.x < left.position.x)

            v.x = left.position.x;

        //最右不能右過右邊界

        if (v.x > right.position.x)

            v.x = right.position.x;

        //高度不能超過邊界

        if (v.y > left.position.y)

            v.y = left.position.y;

        return v; //返回被限制后的坐標(biāo)

    }

}

 

.DeathBalance

腳本說明:

1.按暫停或游戲結(jié)束時(shí)會(huì)彈出的菜單面板;

2.菜單面板會(huì)顯示本局分?jǐn)?shù)和最高分?jǐn)?shù),有重啟游戲和退出游戲的按鈕;

using System;

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.SceneManagement;

using UnityEngine.UI;

 

public class DeathBalance : MonoBehaviour //掛死亡面板DeathPanel

{

    public Text score; //把當(dāng)前分?jǐn)?shù)ScoreText拖進(jìn)去

    public Text bureauScore; //把本局分?jǐn)?shù)BureauScore拖進(jìn)去

    public Text topScore; //把最高分?jǐn)?shù)TopScore拖進(jìn)去

    private void OnEnable()

    {

        bureauScore.text = score.text; //結(jié)算本局分?jǐn)?shù)    

        if (PlayerPrefs.HasKey("分?jǐn)?shù)")) //如果已經(jīng)存儲(chǔ)了分?jǐn)?shù)

            topScore.text = PlayerPrefs.GetString("分?jǐn)?shù)");  //就獲取上次存的最高分?jǐn)?shù)

        //讓本局分?jǐn)?shù)和最高分?jǐn)?shù)比較,如果本局分?jǐn)?shù)比最高分?jǐn)?shù)大

        if (Convert.ToInt32(bureauScore.text) > Convert.ToInt32(topScore.text))

        {

            topScore.text = bureauScore.text; //更新最高分?jǐn)?shù)

            PlayerPrefs.SetString("分?jǐn)?shù)", bureauScore.text); //存儲(chǔ)最高分?jǐn)?shù)       

        }

    }

    public void RestartGame() //重新開始,掛按鈕RestartGame

    {

        SceneManager.LoadScene("ElasticBall"); //加載場(chǎng)景(提前保存一個(gè)場(chǎng)景)

    }

    public void QuitGame() //退出游戲,掛按鈕QuitGame

    {

        Application.Quit();

    }

}

 

.Enemy

腳本說明:掛幾何體(敵人)身上,實(shí)時(shí)監(jiān)測(cè)自身血量,血量<=0時(shí)自動(dòng)銷毀。

using System;

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

/// <summary>

/// 掛每個(gè)幾何體上

/// </summary>

public class Enemy : MonoBehaviour

{

    Text number; //聲明數(shù)字

    private void Start()

    {

        number = GetComponentInChildren<Text>(); //找到子物體(數(shù)字)

    }

    private void Update()

    {

        if (Convert.ToInt32(number.text) < 1) //如果數(shù)字小于1時(shí)

            Destroy(gameObject); //銷毀幾何體自身

    }

}

 

.BigBall

腳本說明:小球碰到后直徑會(huì)變大20%,攻擊力翻倍,標(biāo)簽也會(huì)更改,永久效果,且只能變大一次。

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

/// <summary>

/// //掛變大道具上

/// </summary>

public class BigBall : MonoBehaviour

{

    private void OnCollisionEnter2D(Collision2D collision) //被碰撞是調(diào)用

    {

        if (collision.gameObject.tag != "BigBall") //當(dāng)普通小球碰到時(shí)

        {

            collision.transform.localScale *= 1.2f;//小球變大20%成打球

            collision.gameObject.tag = "BigBall"; //大球的標(biāo)簽設(shè)為“BigBall”

        }

        Destroy(gameObject); //銷毀變大道具

    }

}

 

十一.CopyBall

復(fù)制道具:小球或打球碰到后會(huì)從預(yù)支件創(chuàng)建一個(gè)小球供玩家調(diào)配,

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

/// <summary>

/// 掛復(fù)制道具上

/// </summary>

public class CopyBall : MonoBehaviour

{

    //小球需要做一個(gè)預(yù)制件拖進(jìn)來

    public Transform ball;

    private void OnCollisionEnter2D(Collision2D collision)//被小球碰到時(shí)調(diào)用

    {

        //獲取小球transform組件

        Transform tf = collision.transform;

        //在小球位置復(fù)制一個(gè)新小球(小球預(yù)制件)

        Transform newBall = Instantiate(ball, tf.position,tf.rotation);

        //新小球認(rèn)小球的父物體“Balls”為自己的父物體

        newBall.parent = tf.parent;

        //新小球往右跳    

        newBall.GetComponent<Rigidbody2D>().AddForce(transform.right * 0.02f);

        //舊小球往左跳

        tf.GetComponent<Rigidbody2D>().AddForce(-transform.right * 0.02f);

        //銷毀復(fù)制道具

        Destroy(gameObject);

    }

}

 

步驟全部完畢,代碼中一些參數(shù)可隨個(gè)人喜好隨意設(shè)定,如預(yù)制件生成幾率,瞄準(zhǔn)發(fā)射范圍,槍口位置,關(guān)卡格子布局等等。


游戲基本就做好啦。我們來看一下運(yùn)行的效果:

下面是工程鏈接:https://github.com/wushupei/PhysicalBall

 

最后想系統(tǒng)學(xué)習(xí)游戲開發(fā)的童鞋,歡迎訪問 http://levelpp.com/

游戲開發(fā)攪基QQ群:869551769

微信公眾號(hào):皮皮關(guān)

Unity快速上手系列之2:2D物理彈球的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國家法律
武冈市| 平舆县| 瓦房店市| 民乐县| 岱山县| 揭东县| 宜川县| 开阳县| 久治县| 丰宁| 汉源县| 新野县| 绥德县| 阜康市| 正宁县| 宜君县| 甘泉县| 军事| 黄龙县| 恭城| 元谋县| 广东省| 团风县| 濮阳县| 桦川县| 泽普县| 北碚区| 弋阳县| 新巴尔虎左旗| 应城市| 剑川县| 桐柏县| 本溪市| 那曲县| 鱼台县| 鄂托克前旗| 丰原市| 钟山县| 镇康县| 梅河口市| 理塘县|