Unity實驗一 ---吃小球游戲


一、實驗概述

1.1實驗名稱:

Roll a ball

1.2實驗目的:

本次實驗的總的目的是通過具體的程序的編寫與unity軟件相結合,將所學的知識內化,即將在課堂上學到的知識集成在一起,並實現相關功能,從而鍛煉自己的程序編寫、程序調試能力以及對unity的掌握能力。

1.3實驗內容:

實驗內容是使用Unity軟件完成一個小球滾動吃掉小立方體的游戲。

本次實驗是以windows操作系統為平台,通過unity軟件進行本次實驗的項目實現,unity是一個十分優秀的全面整合的專業游戲引擎。通過unity軟件和編程工具的結合可以輕松創建各種3D模型,模擬模型動態以及插入互動內容。

1.4實驗要求:

基本要求:

1.構建一個小球滾動的游戲場景;

2.創建一個小球,按鍵盤上的上下左右鍵,小球會朝相應的方向移動,小球移動的時候相機也要相應移動。

3.在場景中創建多個立方體,每個立方體都在旋轉;小球與立方體發生碰撞的時候,立方體消失,計分板上得分加“1”。

4.當得分達到“5”分時,在屏幕上顯示“XXX同學,你贏了!”,如果不能輸出中文,可以用英文代替。

 

加分項目:

  1. 添加小球和立方體發生碰撞的特效,添加立方體隨機生成,添加小球撞擊阻礙物的物理效果。
  2. 你能想到的可以實現的其他效果。

1.4實驗開發步驟指導

l  創建地面並貼上紋理

l  創建player

l  設置攝像機

l  隨機創建食物

l  設置碰撞

l  得分音效

l  計分板與獲勝

l  隨機阻礙物

l  player和food觸發特效

l  設置退出和重新開始

二、實驗過程

提前導入unitychan的包

1.創建地面並貼上紋理

(1) 創建plane並修改大小至合適

(2) 創建材質GroundMaterial並在Albedo處添加貼圖

2.創建player

(1)  設置player,放入場景

(2)  創建Animation Controller(player),添加Animator中的controller 

(3)  添加rigidbody 並取消Use Gravity。

   否則由於重力原因會使unitychan下墜 

(4)  設置animator

A.創建BlendTree,添加動作

 

B.調整PosX和PosY

 

C.設置參數inputH和inputY,分別代表水平方向和豎直方向,通過這兩個個參數的改變,可以調整動作的狀態。

(5)  添加腳本使人物可以進行移動

代碼思路:從鍵盤的上下左右鍵獲取用戶的輸入,通過blendTree控制向前向后向左向右的四個運動狀態,同時發生一定的旋轉,改變方向。

1.        //從鍵盤獲取獲取inputHinputV  

2.        inputH = Input.GetAxis("Horizontal");  

3.        inputV = Input.GetAxis("Vertical");  

4.        //設置值  

5.        anim.SetFloat("inputH", inputH);  

6.        anim.SetFloat("inputV", inputV);  

7.        //計算位移  

8.        Vector3 moveX = transform.right * inputH * 100f * Time.deltaTime *speed;  

9.        Vector3 moveZ = transform.forward *inputV * 100f * Time.deltaTime *speed;  

10.    float rotey = inputH * 30f * Time.deltaTime * speed;  

11.    //進行移動  

12.    rbody.velocity = moveX + moveZ;  

13.    //rbody.velocity = new Vector3(moveX, 0f, moveZ);  

14.    this.transform.Rotate(new Vector3(0, rotey, 0)); 

(6)  設置角色與場景間位移

取消勾選Apply Root Motion勾上apply root motion對象的Transfrom變動會基於動畫移動,不受腳本控制。 勾掉則Transform受到腳本控制。

3.設置攝像機

1)跟隨player移動

main camera 設置為unitychan的子對象,則可以跟隨player的移動而移動。



2)第三人稱視角。

設置相機的位置,使其位於player的背后

3)設置camera

 

最終效果:

4.隨機創建食物

plane上隨機位置隨機時間間隔生成一個cube,如果沒有被觸發則在15s后銷毀。

(1)  創建prefab

我們會在游戲中產生許多屬性相同的小Cube作為食物,如果要控制每一個食物隨機間隔時間出現,通過將其設為預制體可以減輕很多工作量。比如,給預制體添加一個腳本,則由預制體而來的游戲對象都有該腳本。

(2)  貼圖

創建一個 Cube Material,賦給food

(3)  設置旋轉

給預制體food添加腳本CubeRotate控制立方體的旋轉。

選用transform.Rotate函數

function Rotate (axis : Vector3, angle : float, relativeTo : Space = Space.Self) : void

transform.Rotate(new Vector3(0f, 1f, 1f));

 

(4)  隨機出現

通過腳本設置食物在plane中隨機時間,隨機位置產生。並且在15s沒有被吃時銷毀。

A.新建一個空的GameObject,添加腳本FoodControl

代碼如下:

 
     void Start () {
        float groundwidth=ground.GetComponent<Renderer>().bounds.extents.x;
        float foodwidth = myfood.GetComponent<Renderer>().bounds.extents.x;
        maxWidth = groundwidth - foodwidth;
        // Vector3 screnpos = new Vector3(Screen.width, 0, 0);
        // Vector3 moveWidth = Camera.main.ScreenToWorldPoint(screnpos);
        //食物自身寬度
        //maxWidth = moveWidth.x - foodwidth;
    }

    // Update is called once per frame
    void Update () {
        time -= Time.deltaTime;
        if (time < 0)
        {
            //產生一個隨機數,代表實例化下一個food所需要的時間
            time = Random.Range(1.5f, 2.0f);
            //產生隨機數Posx,PosY,代表實例化food的坐標
            float posX = Random.Range(-maxWidth, maxWidth);
            float posY = Random.Range(-maxWidth, maxWidth);
            Vector3 spawnPositon = new Vector3(posX, 2f, posY);
            //實例化food,15秒后銷毀
            newmyfood = (GameObject)Instantiate(myfood, spawnPositon, Quaternion.identity);
            Destroy(newmyfood, 15);
        }
        }

 

 

B.設置參數

 

運行效果:


5.設置碰撞

1)為player添加Box Collider組件,編輯范圍

2) 碰撞檢測

A.在MonoBehaviour類中,OnCollisionEnterOnCollisionExitOnCollisionStay是碰撞時的回調方法,可以在腳本中重載它們。當綁定了Collision腳本組件的游戲物體發生碰撞時,OnCollisionEnter便會被觸發調用一次。然后,在整個碰撞過程中會持續調用OnCollisionStay方法,直到碰撞接觸被解除時,OnCollisionExit被觸發一次。這三個方法都有一個Collision類型的參數,用於保存碰撞信息。

 

撞檢測
    /*
    void OnCollisionEnter(Collision collision)
    {   //獲取碰撞到的游戲物體上的Collider
        // string name = collision.collider.name;
        //  print(name);
        if (collision.collider.tag == "food")
        {
            Destroy(collision.collider.gameObject);
        }
    }
    */

 

 

 

B.添加腳本后,給playerRigidBody設置Constraints


3)觸發檢測

使用碰撞檢測,發生碰撞的游戲物體之間會有碰撞模擬,例如撞到東西會反彈或者停頓一下。如果只想要檢測物體與物體之間是否發生接觸,但是不要產生碰撞的效果,可以使用觸發器來進行接觸檢測。

這樣在游戲物體發生接觸的時候就不會有碰撞的效果了,而是會直接穿過去。Unity的碰撞器有很多類型,Cube的碰撞器類型是盒子碰撞器,另外還有球形碰撞器、膠囊體碰撞器等。

A.food設為觸發器類型

B.設置腳本

使用MonoBehaviour類的OnTriggerEnterOnTriggerExitOnTriggerStay是觸發檢測的三個回調方法,OnTriggerEnter在游戲物體發生接觸時調用一次,OnTriggerExit在游戲物體完全分離時調用一次,而OnTriggerStay在游戲物體接觸過程中持續調用。 觸發器回調的這三個方法的參數都是Collider類型,表示的就是被碰撞的游戲物體的觸發器組件對象。

在本次實驗中使用的是OnTriggerEnter

 

 void OnTriggerEnter(Collider collider)
    {
        if (collider.tag == "food")
        {
            GetComponent<AudioSource>().Play();
            GameObject neweffect = (GameObject)Instantiate(effect, transform.position, effect.transform.rotation);
            neweffect.transform.parent = transform;
            Destroy(neweffect, 1.0f);
            score++;
            

            if (score == 5)
            {
                wintext.SetActive(true);
                wininmage.SetActive(true);
                var z=GameObject.FindGameObjectsWithTag("food");
                for(int i=1;i<z.Length;i++)
                { Destroy(z[i]); }
               
                got.GetComponent<FoodControl>().enabled =  false;
            }
            Destroy(collider.gameObject);
            text.text = "your score:"+score.ToString();
        }
    }

 


5)觸發后cube消失

當檢測到觸發后,說明player吃到了食物,就要將食物銷毀。通過調用Destroy(),可以銷毀想要銷毀的游戲對象。

觸發器回調的參數都是Collider類型,表示的就是被碰撞的游戲物體的觸發器組件對象。因此在Destroy()中傳入collider.gameObject即可。


6.得分音效

1)添加AudioSource

為避免在游戲啟動時開啟音效,取消勾選Play On Awake

 2)播放

在腳本中觸發檢測中添加代碼

7.計分板與獲勝

1)計分

player吃到food后分數會上升

這一功能主要在觸發檢測中實現,通過定義一個intscore,來記錄吃到food的個數,每當有觸發被檢測到,說明player吃到了food,則score加一。

2)計分板

Unity中使用UI可以通過GUIUGUI。在這里使用的是UGUI。但在操作過程中確實感受到了如果要想設置成自己想要的界面狀態,需要大量的調整。

添加畫布,添加text對象,通過在代碼中控制文本來顯示分數。

 

 void OnGUI()
    {
        GUIStyle style = new GUIStyle();
        style.normal.background = null;
        style.normal.textColor = new Color(0, 0, 0);
        style.fontSize = 15;
        GUI.Label(new Rect(100, 20, 100, 40), "your score:" + score, style);
    }

 

3youwin

canvas中添加textimage,但並不顯示,當score達到5后,通過代碼進行顯示。

效果截圖:

     

4)勝利后清理環境

當吃到五個食物后,清理環境中剩下的食物,並且停止產生新的食物。

A.清理剩下的食物

通過GameObject.FindGameObjectsWithTag()方法來獲取所有標簽為“food”的食物,並一一銷毀。

var z=GameObject.FindGameObjectsWithTag("food");
                for(int i=1;i<z.Length;i++)
                { Destroy(z[i]); }


B.停止產生新食物

通過關閉產生食物的腳本來停止產生新食物。

 got.GetComponent<FoodControl>().enabled =  false;


8.隨機阻礙物

隨即阻礙物的實現類似於隨機生成食物。

(1)  創建prefabs

(2)  添加腳本

隨機生成一個數字a,在場景中生成相應個數的障礙物,player碰到障礙物時會被阻擋。

 

void Start () {
        a = Random.Range(1, 4);    //生成 [1,4) 的隨機整數
        float groundwidth = ground.GetComponent<Renderer>().bounds.extents.x;
        float foodwidth = myban.GetComponent<Renderer>().bounds.extents.x;
        maxWidth = groundwidth - foodwidth;
    }
    
    // Update is called once per frame
    void Update () {
        if (a > 0)
        { 
            float posX = Random.Range(-maxWidth, maxWidth);
            float posY = Random.Range(-maxWidth, maxWidth);
            Vector3 spawnPositon = new Vector3(posX, 1f, posY);
            //實例化阻礙物
            newmyban = (GameObject)Instantiate(myban, spawnPositon, Quaternion.identity);
            a--;
        }
    }

 

 

 

效果截圖

9.playerfood觸發特效

(1)  導入effects資源


(2)  編寫代碼

在觸發檢測中添加以下代碼,使得出發時播放effct效果,1s后銷

            GameObject neweffect = (GameObject)Instantiate(effect, transform.position, effect.transform.rotation);
            neweffect.transform.parent = transform;
            Destroy(neweffect, 1.0f);

效果截圖:


10.設置退出和重新開始

1)利用UGUI,設置兩個buttonexitrestart

2)添加響應事件

代碼如下:

1.        public void ReStart()  

2.            {  

3.                score = 0;  

4.                wintext.SetActive(false);  

5.                wininmage.SetActive(false);  

6.                exitbutton.SetActive(false);  

7.                restartbutton.SetActive(false);  

8.                got.GetComponent<FoodControl>().enabled = true;  

9.            }  

 

1.        public void GameExit()  

2.        {  

3.            Application.Quit();  

4.        }  

 

10.設置空氣牆

1)添加4cube,分別調整至周圍

2)勾除mesh render

 

最后的效果~~

 

 



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM