unity之跳一跳(完整版)

1.場景

(1)creat->3D objict->plane 並重命名爲ground,做爲地面(如下圖)圖一
(2)並調整顏色,大小至適合(如下圖)
調正顏色:創建material(project:creat->Material)用與當作groud的材質,調整顏色,並賦到ground上
在這裏插入圖片描述
在這裏插入圖片描述

2.製作模型(即預製體:prefab)

(1)創建盒子:creat,調整盒子大小及位置,並將其拖入到事先建立好的prefabs文件夾中,使之作爲一個預製體
在這裏插入圖片描述
(2)創建人物:
建立一個空物體(Creat empty),並將其重命名爲player
在這裏插入圖片描述
在player裏建立一個圓柱和球體,給player添加剛體組件,調正顏色(過程和標題1中ground的調色差不多),調正大小比例使其形成下圖模樣(圖中transform參數可作爲參考)
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
至此我們遊戲所需模型製作完畢

3.生成第二個盒子

創建Scripts文件夾,在其中創建C#腳本(C# Script)
在這裏插入圖片描述
打開編輯(話不多說,上代碼)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class player : MonoBehaviour
{
    public float maxDis;//生成盒子與上一個盒子的最大距離
    public GameObject _box;//獲取生成的盒子對應的預製體
    

    private Vector3 _dir = new Vector3(1, 0, 0);//生成第二個盒子的方向變量
    private Rigidbody rig1;//獲取player剛體組件
    // Start is called before the first frame update
    void Start()
    {
        rig1 = GetComponent<Rigidbody>();//獲取player的Rigidbody組件,因爲此腳本掛在player上,所以默認獲取player的剛體組件,可以查資料學習一下怎樣獲取指定物體組件
        putBox();//調用生成盒子函數
    }

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

    void putBox()
    {
        var box = Instantiate(_box);//實例化盒子
        box.transform.position = _box.transform.position + _dir * Random.Range(3f, maxDis);//設置盒子位置
        var a = Random.Range(1f, 2);//生成一個隨機數
        box.transform.localScale = new Vector3(a, 1.108432f, a);//改變盒子scale(尺寸)中的x(長)與z(寬)全部爲生成的隨機數
    }

    void Random_dir()//隨機盒子生成方向
    {
        var a = Random.Range(0, 2);//隨機生成0,1兩個數
        if (a == 0)
        {
            _dir = new Vector3(1, 0, 0);
        }
        else
        {
            _dir = new Vector3(0, 0, 1);
        }
    }
}

編輯完後 ctrl+s保存,返貨到unity界面執行下面操作
在這裏插入圖片描述
運行結果如圖
在這裏插入圖片描述
至此我們完成了生成盒子的操作

4.使player能夠完成跳動

在腳本中updata中添加如下代碼

if (Input.GetKeyDown(KeyCode.Space))//判斷是否按下space
        {
            start_time = Time.time;//記錄按下space的時間
        }

        if (Input.GetKeyUp(KeyCode.Space))//判斷是否鬆開按鍵
        {
            var time = Time.time - start_time;//計算按鍵時間
            jump(time);
        }

創建使player跳躍函數

void jump(float time)
    {
        //給player添加瞬間力
        //Factor爲控制player跳躍速度的控制基數
        rig1.AddForce((new Vector3(0, 2, 0) + _dir) * time * Factor, ForceMode.Impulse);
    }

5.調整player的重心

我們發現此實player跳躍後容易摔倒,所以我們要經過下面操作調整player重心,使其不倒

首先在player上建立空物體,並將其位置移動到player最低端在這裏插入圖片描述

然後通過代碼調正重心
在這裏插入圖片描述
在這裏插入圖片描述

6.實現盒子及player按下space時的動畫

在這裏插入圖片描述
將updata中代碼改成這樣

if (Input.GetKeyDown(KeyCode.Space))//判斷是否按下space
        {
            _head = head.transform.localPosition;//記錄縮放前頭部位置
            _body = body.transform.localScale;//記錄縮放前身體大小
            _stand_box = stand_box.transform.localScale;//記錄盒子大小
            start_time = Time.time;//記錄按下space的時間
        }

        if (Input.GetKeyUp(KeyCode.Space))//判斷是否鬆開按鍵
        {
            var time = Time.time - start_time;//計算按鍵時間
            jump(time);
            body.transform.localScale = _body;//身體還原
            head.transform.localPosition = _head;
            stand_box.transform.localScale = _stand_box;//盒子還原
        }
        if (Input.GetKey(KeyCode.Space))
        {

            head.transform.localPosition += new Vector3(0, -1, 0) * 0.1f * Time.deltaTime;//頭動畫縮小
            body.transform.localScale += new Vector3(1, -1, 1) * 0.05f * Time.deltaTime;//身體動畫縮小

            stand_box.transform.localScale += new Vector3(1, -1, 1) * 0.05f * Time.deltaTime;//盒子動畫縮小

        }

7.當player跳落在盒子上生成下一個盒子以及銷燬前一個盒子

當判斷player落在盒子上時,要使用碰撞事件函數,而碰撞事件函數的基條件是存在碰撞器,所以我們要在player和盒子上添加碰撞器(collider)
在這裏插入圖片描述
然後調成碰撞其大小及位置使其將player完全籠罩
(盒子碰撞器添加方法和player相似 在此不多說,注意:盒子添加完碰撞器後要將prefab中的盒子替換

然後我們需要添加碰撞事件的函數

  void OnCollisionEnter(Collision collision)//碰撞事件函數
    {
        Debug.Log(collision.gameObject.name);//打印與player碰撞的物體的名字
        Collider collider_box = stand_box.GetComponent<Collider>();//獲取player原來所在盒子的碰撞器
        if (collision.gameObject.name.Contains("Cube") && collider_box != collision.collider)//判斷是否與盒子碰撞且碰撞的盒子是否不同於上一個盒子
        {
            GameObject destory_box = stand_box;//定義將要銷燬的盒子
            stand_box = new_box;//將player所在盒子進行刷新
            putBox();//生成新的盒子
            Destroy(destory_box);

        }
        if (collision.gameObject.name == "ground")
        {
            SceneManager.LoadScene(0);//重新開始遊戲,需要引入頭文件:using UnityEngine.SceneManagement;
        }
    }

同時需要將原來的代碼進行少許改動
在這裏插入圖片描述
在這裏插入圖片描述

運行了一下,發現盒子生成時可能會產生bug:盒子會形成相互重疊,原因是盒子大小和生成距離的範圍有關,自行進行調整即可
在這裏插入圖片描述
在這裏插入圖片描述

還有一個bug就是盒子總是按照一個方向生成,原因是在生成盒子函數中未調用隨機生成方向函數,自己填補即可

8.實現相機跟隨

首先需要定義一個相機的位置的公共變量和一個相機與player位之差的常量
在這裏插入圖片描述
然後在腳本執行開始時計算相機與player的位置差
在這裏插入圖片描述
隨後添加相機移動函數

void MoveCamera()//相機跟隨函數
    {
        Camera.position = transform.position + _cameraRelativeTranfrom;//移動相機:相機位置等於小人目前位置加相對位置
    }

9.分數顯示

創建text 並將其位置進行調整,然後在屬性欄中進行自適應(途中將其設置爲左上角顯示)
自適應之後無論裝口大小怎樣改變,其位置依然在左上角
在這裏插入圖片描述
添加下面兩個變量
在這裏插入圖片描述
在start中初始化
在這裏插入圖片描述
在成功跳躍後分數加一
在這裏插入圖片描述

10.蓄力效果

在player中添加例子特效(如圖),並對其在屬性欄中進行大小形狀設置
在這裏插入圖片描述

在代碼中定義public Object lizi;

開啓代碼:lizi.SetActive(true);
關閉代碼:lizi.SetActive(false);

整個程序源碼

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class player : MonoBehaviour
{
    public GameObject stand_box;//當前player所在盒子
    public float maxDis;//生成盒子與上一個盒子的最大距離
    public GameObject _box;//獲取生成的盒子對應的預製體
    public float Factor;//實現速度基數
    public Transform transform1;//獲取player中空物體的位置
    public Transform head;//記錄player的頭部位置
    public Transform body;//記錄player的身體位置
    public Transform Camera;//相機位置,實現相機跟隨時用到
    public Text sco;//記錄分數,需要添加:using UnityEngine.UI;
    public GameObject lizi;//例子特效


    private Vector3 _dir = new Vector3(1, 0, 0);//生成第二個盒子的方向變量
    private Rigidbody rig1;//獲取player剛體組件
    private float start_time;//記錄按下開始space的時間
    private GameObject new_box;//新生成的盒子
    private static Vector3 _cameraRelativeTranfrom;//相機需要移動距離
    //記錄player位置和大小及當前盒子大小
    Vector3 _head = new Vector3(0, 0, 0);
    Vector3 _body = new Vector3(0, 0, 0);
    Vector3 _stand_box = new Vector3(0, 0, 0);
    private int _sco;

    // Start is called before the first frame update
    void Start()
    {
        lizi.SetActive(false);//默認粒子特效爲關閉狀態
        _sco = 0;//分數初始化
        sco.text = _sco.ToString();//分數更新
        _cameraRelativeTranfrom = Camera.position - transform.position;//計算相機對於player的相對位置
        rig1 = GetComponent<Rigidbody>();//獲取player的Rigidbody組件,因爲此腳本掛在player上,所以默認獲取player的剛體組件,可以查資料學習一下怎樣獲取指定物體組件
        rig1.centerOfMass = transform1.localPosition;//將物體重心放在playwe中空物體的位置
        putBox();//調用生成盒子函數
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))//判斷是否按下space
        {
            lizi.SetActive(true);//開啓粒子特效
            _head = head.transform.localPosition;//記錄縮放前頭部位置
            _body = body.transform.localScale;//記錄縮放前身體大小
            _stand_box = stand_box.transform.localScale;//記錄盒子大小
            start_time = Time.time;//記錄按下space的時間
        }

        if (Input.GetKeyUp(KeyCode.Space))//判斷是否鬆開按鍵
        {
            lizi.SetActive(false);//關閉粒子特效
            var time = Time.time - start_time;//計算按鍵時間
            jump(time);
            body.transform.localScale = _body;//身體還原
            head.transform.localPosition = _head;
            stand_box.transform.localScale = _stand_box;//盒子還原
        }
        if (Input.GetKey(KeyCode.Space))
        {

            head.transform.localPosition += new Vector3(0, -1, 0) * 0.1f * Time.deltaTime;//頭動畫縮小
            body.transform.localScale += new Vector3(1, -1, 1) * 0.05f * Time.deltaTime;//身體動畫縮小

            stand_box.transform.localScale += new Vector3(1, -1, 1) * 0.05f * Time.deltaTime;//盒子動畫縮小

        }
    }

    void putBox()
    {
        Random_dir();//調用隨機生成盒子方向函數
        new_box = Instantiate(_box);//實例化盒子
        new_box.transform.position = stand_box.transform.position + _dir * Random.Range(4.5f, maxDis);//設置盒子位置
        var a = Random.Range(1f, 2);//生成一個隨機數
        new_box.transform.localScale = new Vector3(a, 1.108432f, a);//改變盒子scale(尺寸)中的x(長)與z(寬)全部爲生成的隨機數
    }

    void Random_dir()//隨機盒子生成方向
    {
        var a = Random.Range(0, 2);//隨機生成0,1兩個數
        if (a == 0)
        {
            _dir = new Vector3(1, 0, 0);
        }
        else
        {
            _dir = new Vector3(0, 0, 1);
        }
    }

    void jump(float time)
    {
        //給player添加瞬間力
        //Factor爲控制player跳躍速度的控制基數
        rig1.AddForce((new Vector3(0, 2, 0) + _dir) * time * Factor, ForceMode.Impulse);
    }

    void OnCollisionEnter(Collision collision)//碰撞事件函數
    {
        Debug.Log(collision.gameObject.name);//打印與player碰撞的物體的名字
        Collider collider_box = stand_box.GetComponent<Collider>();//獲取player原來所在盒子的碰撞器
        if (collision.gameObject.name.Contains("Cube") && collider_box != collision.collider)//判斷是否與盒子碰撞且碰撞的盒子是否不同於上一個盒子
        {
            _sco++;//分數加一
            sco.text = _sco.ToString();//將分數更新
            MoveCamera();
            GameObject destory_box = stand_box;//定義將要銷燬的盒子
            stand_box = new_box;//將player所在盒子進行刷新
            putBox();//生成新的盒子
            Destroy(destory_box);

        }
        if (collision.gameObject.name == "ground")
        {
            SceneManager.LoadScene(0);//重新開始遊戲,需要引入頭文件:using UnityEngine.SceneManagement;
        }
    }

    void MoveCamera()//相機跟隨函數
    {
        Camera.position = transform.position + _cameraRelativeTranfrom;//移動相機:相機位置等於小人目前位置加相對位置
    }
}

工程下載地址:鏈接:https://pan.baidu.com/s/16_drASFV6Fk5ILGQU5QGlA
提取碼:ew0g

unity開發跳一跳至此告一段落
留給大家些許bug,評論區見,歡迎大家前來指點

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章