unity飛機大戰(2)一些細節問題

對象池補充

先說下上一篇對象池的一個問題。用腳本,在一個SpawnPool,添加多個prefab,

運行遊戲時,只有第一個prefab預加載了規定個數,當用到其他prefab時,

其他prefab纔出現在pool中,而且數量會無限增加! 但是第一個prefab卻不會,

還是會限制在 limitAmount規定的個數。如果將一個對象對應一個SpawnPool,運行時正常! 

這個問題很是詭異,目前還沒有找到原因。


解決方法就是 不用腳本初始化,而是用插件事先編輯好對象池,運行! 沒有任何問題

using UnityEngine;
using System.Collections;
using PathologicalGames;

public class SpawnTest : MonoBehaviour {

    public GameObject prefab, prefab1;
    //對象池
    SpawnPool spawnPool;
    
	// Use this for initialization
	void Start () {
        spawnPool = PoolManager.Pools["Spawn"];

        //每隔0.5秒,調用一次CreatPerfab方法
        InvokeRepeating("CreatPerfab", 1f, 0.2f);
	}
	
	// Update is called once per frame
	void Update () {

	}
    void CreatPerfab() {
        //從對象池中取出物體,並且設置它的位置
        spawnPool.Spawn(prefab.transform, new Vector3(transform.position.x, transform.position.y, 0), Quaternion.identity);
        spawnPool.Spawn(prefab1.transform, new Vector3(transform.position.x+3f, transform.position.y, 0), Quaternion.identity);
    }
}

幀動畫的播放

飛機幀動畫的循環播放

//每秒幀數
public int frameCountPersconds = 10;
//時間
public float timer  = 0;
//渲染組件
private SpriteRenderer spriteRender;
//代碼實現
timer+=Time.deltaTime;
int frameIndex = (int)(timer/(1f/frameCountPersconds));
int frame = frameIndex%2;
spriteRender.sprite = sprites[frame];

敵機被消滅時播放的一次性幀動畫

		if(isDeath){
				timer+=Time.deltaTime;// 0
				int frameIndex = (int)(timer/(1f/explosionAnimationFrame));
				if(frameIndex>=explosionSprites.Length){
                    this.gameObject.SetActive(false);
				}else{
					render.sprite= explosionSprites[frameIndex];
				}

遊戲暫停

Time.timeScale = 0;//暫停

瞭解更多,可以學習雨鬆的這篇文章:Unity3D研究院之Time.timeScale、遊戲暫停(七十四)

碰撞檢測

子彈攻擊敵機,敵機與飛機碰撞後,飛機銷燬,遊戲結束都需要碰撞檢測。

物體發生碰撞的必要條件

兩個物體都必須帶有碰撞器(Collider),其中一個物體還必須帶有Rigidbody剛體。

在unity3d中,能檢測碰撞發生的方式有兩種,一種是利用碰撞器,另一種則是利用觸發器。

碰撞器: 一羣組件,它包含了很多種類,比如:Box Collider(盒碰撞體),Mesh Collider(網格碰撞體)等,這些碰撞器應用的場合不同,但都必須加到GameObjecet身上。

觸發器 ,只需要在檢視面板中的碰撞器組件中勾選IsTrigger屬性選擇框。

觸發信息檢測:


1.MonoBehaviour.OnTriggerEnter(Collider collider)當進入觸發器

2.MonoBehaviour.OnTriggerExit(Collider collider)當退出觸發器

3.MonoBehaviour.OnTriggerStay(Collider collider)當逗留觸發器

碰撞信息檢測:

1.MonoBehaviour.OnCollisionEnter(Collision collision) 當進入碰撞器

2.MonoBehaviour.OnCollisionExit(Collision collision) 當退出碰撞器

3.MonoBehaviour.OnCollisionStay(Collision collision)  當逗留碰撞器

unity3d中的碰撞器和觸發器的區別:

當Is Trigger=false時,碰撞器根據物理引擎引發碰撞,產生碰撞的效果,可以調用OnCollisionEnter/Stay/Exit函數;

當Is Trigger=true時,碰撞器被物理引擎所忽略,沒有碰撞效果,可以調用OnTriggerEnter/Stay/Exit函數。

如果既要檢測到物體的接觸又不想讓碰撞檢測影響物體移動或要檢測一個物件是否經過空間中的某個區域這時就可以用到觸發器

所以在飛機大戰中,我們要給飛機和子彈添加上碰撞器和剛體組件,

同時爲了避免有碰撞效果,我們在飛機和子彈的碰撞器組件上,勾選使用觸發器 Is Trigger=true



給敵機和獎勵物品添加上碰撞器組件


這樣我們就可以在腳本內通過方法來處理邏輯了

    //當子彈碰撞到敵機
	void OnTriggerEnter2D(Collider2D other) {
		if(other.tag=="Enemy"){
			if(!other.GetComponent<Enemy>().isDeath){
				other.gameObject.SendMessage("BeHit");
                this.gameObject.SetActive(false);
			}
		}
	}

遊戲界面

開始界面 遊戲進行 遊戲結束

使用UGUI製作遊戲界面

我的結構是 製作三個界面的面板,通過一個單例的UIManager腳本來控制UI的邏輯

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class UImanager : MonoBehaviour {

    public static UImanager _instance;
    //三個面板
    public GameObject panel_start, panel_run, panel_over;
    //飛機,怪物刷新
    public GameObject hero, spawn;
    // UI:當前分數,最高分數,炸彈個數
    public Text run_curScore, over_curScore, over_highScore, boom;
    //分數 炸彈個數
    public int score,boomCount;
    //遊戲是否暫停
    private bool isRun;
    void Awake(){
        _instance = this;
    }
	void Start () {
        isRun = true;
	}
	
	// Update is called once per frame
	void Update () {
	    if(panel_run.activeSelf){ 
          //  Debug.Log("running!~~~~~~~~");
            run_curScore.text = score.ToString();
            boom.text = "X"+boomCount.ToString();
        }
        if (panel_over.activeSelf)
        {
            over_curScore.text = score.ToString();
            over_highScore.text = GameManager._instance.HistoryHighScore().ToString();
        }
            
	}

    //開始遊戲
    public void StartGame() {
        panel_start.SetActive(false);
        panel_run.SetActive(true);
        hero.SetActive(true);
        spawn.SetActive(true);
    }
    //遊戲結束
    public void OverGame()
    {
        panel_run.SetActive(false);
        panel_over.SetActive(true);
        //hero.SetActive(false);
        //spawn.SetActive(false);
        //spawn.GetComponent<Spawn>().enabled = false;
        //PauseGame();
    }
    //重開一局
    public void ReStartGame()
    {
        panel_over.SetActive(false);
        panel_run.SetActive(true);
        hero.SetActive(true);
        spawn.SetActive(true);
    }
    //退出遊戲
    public void ExitGame()
    {
        Application.Quit();
    }
    //暫停/繼續遊戲
    public void PauseGame()
    {
        if (isRun)
        {
            Time.timeScale = 0;//暫停
            isRun = false;
        }
        else {
            Time.timeScale = 1;
            isRun = true;
        }

    }
}
對於遊戲UI的自適應,還有沒怎麼研究,目前解決的方法就是UGUI自己的自適應,Reference Resolution組件 掛在Canvas上 ,一些ui使用錨點進行定位。

遊戲分數的存儲

    //返回 歷史最高分
    public int HistoryHighScore() {
        int historyScore = PlayerPrefs.GetInt("historyHighScore", 0);
        int nowScore = UImanager._instance.score;
        if (nowScore > historyScore)
        {
            PlayerPrefs.SetFloat("historyHighScore", nowScore);
            historyScore = nowScore;
        }
        return historyScore;
    }

總結

在遊戲最後,可以增加一個分享功能,這裏我想安卓的ShareSDK,在下一篇文章中,我會對此學習,與大家交流~~

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