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,評論區見,歡迎大家前來指點