1. 程式人生 > >Unity實戰篇:移植遊戲到安卓平臺的注意事項及其例項(三)(UI互動邏輯開發)

Unity實戰篇:移植遊戲到安卓平臺的注意事項及其例項(三)(UI互動邏輯開發)

為了方便開發,我們把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%就增加等級。

\boldsymbol{\mathbf{{\color{Red} maxExp=1000*2^{level}}}}

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的邏輯開發到這裡就差不多了