Unity3D初級案例-經典貪吃蛇二
引言:承接上一篇貪吃蛇案例!喜歡我的就關注我啊,不然沒有繼續寫的動力啦!!!
開發版本:unity 2017.1.1f1
適合人群:初學Unity者
原始檔連結請見文末!
開啟學習之旅吧!
07 邊界傳送
完善蛇頭的觸發檢測,使用switch判斷蛇頭碰撞的牆面
//判斷碰撞到物體的名字 switch (collision.gameObject.name) { case "Up": //-transform.localPosition.y + 30 需要注意這裡新增一個偏差值,防止蛇頭剛移動到底部就碰到底部的碰撞器,下面同理 transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y + 30, transform.localPosition.z); break; case "Down": transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y - 30, transform.localPosition.z); break; case "Left": transform.localPosition = new Vector3(-transform.localPosition.x + 210, transform.localPosition.y, transform.localPosition.z); break; case "Right": transform.localPosition = new Vector3(-375, transform.localPosition.y, transform.localPosition.z); break; }
08 設計UI
首先實現分數和長度的記錄
新建MainUIController.cs指令碼,做成單例模式
新增UpdateUI()方法,用於外部呼叫更新UI顯示
private static MainUIController instance; public static MainUIController Instance { get { return instance; } } private void Awake() { if (instance == null) { instance = this; } } public int score = 0; public int length = 0; public Text scoreText; public Text lengthText; public void UpdateUI(int s = 5, int l = 1) { score += s; length += l; scoreText.text = "得分:\n" + score; lengthText.text = "長度:\n" + length; }
然後在SnakeHead.cs的觸發檢測中呼叫
if (collision.gameObject.CompareTag("Food")) { Destroy(collision.gameObject); MainUIController.Instance.UpdateUI(); AddBody(); FoodCreator.Instance.CreateFood((Random.Range(0, 100) < 20) ? true : false); } else if (collision.gameObject.CompareTag("Reward")) { Destroy(collision.gameObject); MainUIController.Instance.UpdateUI(Random.Range(5, 15) * 10); AddBody(); }
設計暫停按鈕,新建Pause按鈕
public bool isPause = false;
public void Pause()
{
isPause = !isPause;
if (isPause)
{
Time.timeScale = 0;
//按鈕圖片的切換
pauseBtn.GetComponent<Image>().sprite = pauseSprites[1];
}
else
{
Time.timeScale = 1;
pauseBtn.GetComponent<Image>().sprite = pauseSprites[0];
}
}
然後將暫停按鈕監聽Pause方法
同理,返回鍵就重新載入場景 注意引用名稱空間using UnityEngine.UI;
public void BackToHome()
{
SceneManager.LoadScene("StartScene");
}
設立一個布林值用來判斷是否有邊界
public bool hasBorder
後續操作待定。。。
09 蛇死亡處理
實現蛇死亡特效
在SnakeHead.cs中新增Die()方法
public GameObject dieEffect;
void Die()
{
audioSource.clip = dieClip;
audioSource.Play();
//取消蛇移動的InvokeRepeating呼叫
CancelInvoke();
isDie = true;
//例項化死亡效果
Instantiate(dieEffect, transform.position - Vector3.forward, Quaternion.identity);
//資料持久化PlayerPrefs以鍵值對的形式儲存資料,可以儲存int、string、float三種資料型別,類似字典
//Set用於儲存資料,Get用於得到資料
PlayerPrefs.SetInt("lastLength", MainUIController.Instance.length);
PlayerPrefs.SetInt("lastScore", MainUIController.Instance.score);
//如果當前分數高於最高分數,就將最高資料進行更換
//GetInt("bestScore", 0)如果當前有bestScore值的話,則返回該值,如果沒有,則返回0
if (PlayerPrefs.GetInt("bestScore", 0) < MainUIController.Instance.score)
{
PlayerPrefs.SetInt("bestLength", MainUIController.Instance.length);
PlayerPrefs.SetInt("bestScore", MainUIController.Instance.score);
}
//開啟協成,呼叫GameOver方法
StartCoroutine(GameOver(1.5f));
}
IEnumerator GameOver(float t)
{
//停頓t秒執行下面語句
yield return new WaitForSeconds(t);
//重新載入到開始場景
UnityEngine.SceneManagement.SceneManager.LoadScene("StartScene");
}
完善蛇頭觸發檢測
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.CompareTag("Food"))
{
Destroy(collision.gameObject);
MainUIController.Instance.UpdateUI();
AddBody();
FoodCreator.Instance.CreateFood((Random.Range(0, 100) < 20) ? true : false);
}
else if (collision.gameObject.CompareTag("Reward"))
{
Destroy(collision.gameObject);
MainUIController.Instance.UpdateUI(Random.Range(5, 15) * 10);
AddBody();
}
else if (collision.gameObject.CompareTag("Body"))
{
Die();
}
else
{
if (MainUIController.Instance.hasBorder)
{
Die();
}
else
{
switch (collision.gameObject.name)
{
case "Up":
transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y + 30, transform.localPosition.z);
break;
case "Down":
transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y - 30, transform.localPosition.z);
break;
case "Left":
transform.localPosition = new Vector3(-transform.localPosition.x + 210, transform.localPosition.y, transform.localPosition.z);
break;
case "Right":
transform.localPosition = new Vector3(-375, transform.localPosition.y, transform.localPosition.z);
break;
}
}
}
}
10 儲存使用者設定
我們使用資料持久化儲存PlayerPrefs來儲存使用者的設定,實現儲存玩家上一次的設定,上一節我們就用該方法儲存了遊戲的得分
需要將蛇頭和所有蛇身的精靈資源放在Resources資料夾中,動態載入資源
新建四個方法BlueSelected(),YellowSelected(),BorderSelected(),NoBorderSelected(),分別繫結開始介面的四個Toggle選項
使用PlayerPrefs來儲存使用者設定
public class StartUIController : MonoBehaviour
{
public Text lastText;
public Text bestText;
public Toggle blue;
public Toggle yellow;
public Toggle border;
public Toggle noBorder;
private void Start()
{
lastText.text = "上次:長度"+PlayerPrefs.GetInt("lastLength",0)+",分數" + PlayerPrefs.GetInt("lastScore", 0);
bestText.text = "最好:長度" + PlayerPrefs.GetInt("bestLength", 0) + ",分數" + PlayerPrefs.GetInt("bestScore", 0);
//GetString如果sh已經有值,則判斷是否為樣式一小蛇,如果使用者還沒有設定,則預設為樣式一
if (PlayerPrefs.GetString("sh", "sb01") == "sb01")
{
blue.isOn = true;
BlueSelected(true);
}
else
{
yellow.isOn = true;
YellowSelected(true);
}
//有無邊界的判斷如上
if (PlayerPrefs.GetInt("border", 0) == 1)
{
border.isOn = true;
BorderSelected(true);
}
else
{
noBorder.isOn = true;
NoBorderSelected(true);
}
}
//選擇了樣式一小蛇
public void BlueSelected(bool isOn)
{
if (isOn)
{
PlayerPrefs.SetString("sh", "sh01");
PlayerPrefs.SetString("sb01", "sb0101");
PlayerPrefs.SetString("sb02", "sb0102");
//如果選擇該樣式,修改圖片顏色,用於區別
blue.GetComponentInChildren<Image>().color = new Color32(1, 159, 232, 90);
}
else
{
blue.GetComponentInChildren<Image>().color = new Color32(1, 159, 232, 50);
}
}
//選擇了樣式二小蛇
public void YellowSelected(bool isOn)
{
if (isOn)
{
PlayerPrefs.SetString("sh", "sh02");
PlayerPrefs.SetString("sb01", "sb0201");
PlayerPrefs.SetString("sb02", "sb0202");
yellow.GetComponentInChildren<Image>().color = new Color32(1, 159, 232, 90);
}
else
{
yellow.GetComponentInChildren<Image>().color = new Color32(1, 159, 232, 50);
}
}
//選擇有邊界模式
public void BorderSelected(bool isOn)
{
if (isOn)
{
PlayerPrefs.SetInt("border", 1);
}
}
//選擇無邊界模式
public void NoBorderSelected(bool isOn)
{
if (isOn)
{
PlayerPrefs.SetInt("border", 0);
}
}
//開始遊戲
public void StartGame()
{
UnityEngine.SceneManagement.SceneManager.LoadScene("MainScene");
}
}
使用者設定已經儲存,需要在遊戲開始後,SnakeHead.cs中動態讀取設定
private void Awake()
{
gameObject.GetComponent<Image>().sprite = Resources.Load<Sprite>(PlayerPrefs.GetString("sh", "sh01"));
bodySprites[0] = Resources.Load<Sprite>(PlayerPrefs.GetString("sb01", "sb0101"));
bodySprites[1] = Resources.Load<Sprite>(PlayerPrefs.GetString("sb02", "sb0102"));
}
在MainUIController.cs中讀取使用者是否設定邊界
private void Start()
{
//判斷是否設定了邊界
if (PlayerPrefs.GetInt("border", 0) == 0)
{
//hasBorder標誌位用於判斷蛇頭碰到邊界是否死亡
hasBorder = false;
//遍歷bgImage父物體下所有子物體
foreach (Transform item in bgImage.gameObject.transform)
{
//在無邊界模式下,禁用掉邊界
item.gameObject.GetComponent<Image>().enabled = false;
}
}
else
{
hasBorder = true;
}
}
新增音效和背景音樂都是相同操作,在此不再贅述!
對了,為了方便,我直接設定螢幕大小為1280*720,只需要在awake方法中加Screen.SetResolution(1280, 720,false);
基本完成遊戲的開發,大家也可以發揮想象力,再添磚加瓦,完善功能!
喜歡小生的請關注我哦!!!
素材及工程檔案:百度雲連結 提取碼:lok4