Unity實戰篇:移植遊戲到安卓平臺的注意事項及其例項(三)(UI互動邏輯開發)
阿新 • • 發佈:2018-12-12
為了方便開發,我們把GameController做成一個單例。
using UnityEngine; using UnityEngine.SceneManagement; using System.Collections; using UnityEngine.UI; public class Done_GameController : MonoBehaviour { private static Done_GameController instance; public GameObject[] hazards; public GameObject[] UIPanels;//儲存三個UIPanel public Vector3 spawnValues; public int hazardCount; public float spawnWait; public float startWait; public float waveWait; public bool gameOver = false; public int level = 1; public int score = 0; public int loadCount = 1; public static Done_GameController Instance { get { return instance; } set { instance = value; } } private void Awake() { Instance = this; UIPanels[0].SetActive(true); } public void StartIEnumerator() { StartCoroutine(SpawnWaves()); } IEnumerator SpawnWaves () { yield return new WaitForSeconds (startWait); while (true) { for (int i = 0; i < hazardCount; i++) { GameObject hazard = hazards [Random.Range (0, hazards.Length)]; Vector3 spawnPosition = new Vector3 (Random.Range (-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z); Quaternion spawnRotation = Quaternion.identity; Instantiate (hazard, spawnPosition, spawnRotation); yield return new WaitForSeconds (spawnWait); } yield return new WaitForSeconds (waveWait); if (gameOver) { break; } } } public void SetPanelInActive(int index) { UIPanels[index].SetActive(false); } public void SetPanelActive(int index) { UIPanels[index].SetActive(true); } }
給GameOverPanel掛載一個指令碼
給GamePanel掛載一個指令碼
給StartPanel掛載一個指令碼
我們再開始做準備工作,將所有的遊戲物體加上碰撞器,並且勾選Is Trigger.
改寫
DestoryByContact
using UnityEngine; using System.Collections; public class Done_DestroyByContact : MonoBehaviour { public GameObject explosion; public GameObject playerExplosion; void OnTriggerEnter (Collider other) { switch (other.tag) { case "PlayerAttack": if(gameObject.tag=="Enemy") { Instantiate(explosion, other.transform.position, other.transform.rotation); Done_GameController.Instance.score += 100; } else if(gameObject.tag=="Stone") { Instantiate(explosion, other.transform.position, other.transform.rotation); Done_GameController.Instance.score += 50; } Destroy(other.gameObject); Destroy(gameObject); break; case "Player": if (gameObject.tag=="EnemyAttack"||gameObject.tag=="Stone"|| gameObject.tag == "Enemy") { Instantiate(playerExplosion, other.transform.position, other.transform.rotation); Done_GameController.Instance.gameOver = true; } Destroy(other.gameObject); Destroy(gameObject); break; default: break; } } }
GameOverPanel指令碼,這裡面涉及到了Dotween外掛的的使用,如果小夥伴們不瞭解這個外掛,就去百度學習一下~
OnComplete(() => SceneManager.LoadScene(0))這句蘭布達表示式意思是當這個動畫執行完畢,才重新載入場景。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using DG.Tweening; using UnityEngine.SceneManagement; public class GameOverPanel : MonoBehaviour { private Text gameOver; private Button reStart; private Button rankingList; private Button backToMenu; private void Awake() { gameOver = transform.Find("GameOver").GetComponent<Text>(); reStart = transform.Find("ReStart").GetComponent<Button>(); rankingList = transform.Find("RankingList").GetComponent<Button>(); backToMenu = transform.Find("BackToMenu").GetComponent<Button>(); } private void Start() { reStart.onClick.AddListener(ReStartGame); rankingList.onClick.AddListener(ToRankingList); backToMenu.onClick.AddListener(BackToMenu); Exit(); } private void Update() { if(Done_GameController.Instance.loadCount==2) { if (Done_GameController.Instance.UIPanels[0].activeSelf == false && Done_GameController.Instance.UIPanels[1].activeSelf == false) { Enter(); Done_GameController.Instance.loadCount++; } } } private void OnEnable() { Done_GameController.Instance.loadCount = 1; Done_GameController.Instance.loadCount++; } private void ToRankingList() { //TODO } private void BackToMenu() { gameOver.transform.DOLocalMoveX(1500, 0.3f); reStart.transform.DOLocalMoveX(1500, 0.6f); rankingList.transform.DOLocalMoveX(1500, 0.9f); backToMenu.transform.DOLocalMoveX(1500, 1.2f); Done_GameController.Instance.gameOver = true; Invoke("InActiveUI", 0.9f); Invoke("SetPanelInActive",0.9f); Done_GameController.Instance.SetPanelActive(0); } private void Enter() { ActiveUI(); gameOver.transform.DOLocalMoveX(0, 0.3f); reStart.transform.DOLocalMoveX(0, 0.6f); rankingList.transform.DOLocalMoveX(0, 0.9f); backToMenu.transform.DOLocalMoveX(0, 1.2f); } private void Exit() { gameOver.transform.localPosition = new Vector3(1500, 433, 0); reStart.transform.localPosition = new Vector3(1500, 201.7f, 0); rankingList.transform.localPosition = new Vector3(1500, -39, 0); backToMenu.transform.localPosition = new Vector3(1500, -282, 0); InActiveUI(); } private void ReStartGame() { gameOver.transform.DOLocalMoveX (1500,0.3f); reStart.transform.DOLocalMoveX(1500, 0.6f); rankingList.transform.DOLocalMoveX(1500, 0.9f); backToMenu.transform.DOLocalMoveX(1500, 1.2f); Done_GameController.Instance.gameOver = false; Invoke("InActiveUI", 0.9f); Invoke("SetPanelInActive", 0.9f); Done_GameController.Instance.SetPanelActive(1); } private void ActiveUI() { gameOver.gameObject.SetActive(true); reStart.gameObject.SetActive(true); rankingList.gameObject.SetActive(true); backToMenu.gameObject.SetActive(true); } private void InActiveUI() { gameOver.gameObject.SetActive(false); reStart.gameObject.SetActive(false); rankingList.gameObject.SetActive(false); backToMenu.gameObject.SetActive(false); } private void SetPanelInActive() { Done_GameController.Instance.SetPanelInActive(2); } private void SetPanelActive() { Done_GameController.Instance.SetPanelActive(2); } }
GamePanel指令碼,其中的經驗值依據當前等級,幾何倍數進行增加。經驗每一次到達100%就增加等級。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
public class GamePanel : MonoBehaviour {
private Text score;
private Text percent_exp;
private Slider exp;
public GameObject player;
private void Awake()
{
score = transform.Find("Score").GetComponent<Text>();
exp = transform.Find("Exp").GetComponent<Slider>();
percent_exp = transform.Find("Exp/Text").GetComponent<Text>();
score.transform.localPosition = new Vector3(-1500, 819, 0);
exp.transform.localPosition = new Vector3(1500, 820, 0);
InActiveUI();
}
private void Update()
{
if(Done_GameController.Instance.loadCount==2)
{
if (Done_GameController.Instance.UIPanels[0].activeSelf == false &&
Done_GameController.Instance.UIPanels[2].activeSelf == false)
{
Done_GameController.Instance.score = 0;
Done_GameController.Instance.level = 1;
StartGame();
Done_GameController.Instance.loadCount++;
}
}
if (Done_GameController.Instance.gameOver)
{
GameOver();
}
score.text = "Score: " + Done_GameController.Instance.score.ToString();
exp.value = Done_GameController.Instance.score / (1000 * (Mathf.Pow(2, Done_GameController.Instance.level)));
percent_exp.text = "Level " + Done_GameController.Instance.level.ToString() + " " + (exp.value*100).ToString()+"%";
if(exp.value>=1)
{
Done_GameController.Instance.level++;
}
}
private void OnEnable()
{
Done_GameController.Instance.gameOver = false;
Done_GameController.Instance.loadCount = 1;
Done_GameController.Instance.loadCount++;
Done_GameController.Instance.StartIEnumerator();
Instantiate(player);
}
public void StartGame()
{
ActiveUI();
score.transform.DOLocalMoveX(-233, 0.5f);
exp.transform.DOLocalMoveX(334, 0.5f);
}
public void GameOver()
{
score.transform.DOLocalMoveX(-1500, 0.5f);
exp.transform.DOLocalMoveX(1500, 0.5f);
Invoke("InActiveUI", 0.5f);
Invoke("SetPanelInActive", 0.5f);
Done_GameController.Instance.SetPanelActive(2);
}
private void ActiveUI()
{
score.gameObject.SetActive(true);
percent_exp.gameObject.SetActive(true);
exp.gameObject.SetActive(true);
}
private void InActiveUI()
{
score.gameObject.SetActive(false);
percent_exp.gameObject.SetActive(false);
exp.gameObject.SetActive(false);
}
private void SetPanelInActive()
{
Done_GameController.Instance.SetPanelInActive(1);
}
private void SetPanelActive()
{
Done_GameController.Instance.SetPanelActive(1);
}
}
總結一下UI邏輯開發,本來我是打算直接使用場景跳轉來實現UI變化的,可是考慮到那種實現方式過於生硬,並且不符合我們的主題——針對Android進行效能優化的主題,所以就寫了這個演算法。其實有一個UI框架https://pan.baidu.com/s/1vxtKrnDo4C23sA9nT0DFyw,它模擬UI的出棧入棧來更方便的調控UI的顯示與隱藏而且他原始碼也很簡單,但是我今天想要自己動手寫一下,其實說來也慚愧,我演算法寫到一半了,才想起來那個UI框架的思想。我這個演算法是判定是否除了想要顯示的UIPanel其他的UIPanel均為失活狀態來更新狀態。這個演算法不看也罷。
好了,主要UI的邏輯開發到這裡就差不多了