siki学院_Unity初级案例_愤怒的小鸟_学习笔记3/3
說明:本次學(xué)習(xí)開始于2018年9月23日,至9月26日已看完全部教學(xué)視頻,并已基本完成該案例的制作,歷時四天。本文檔為我在學(xué)習(xí)過程中,通過記事本記錄的學(xué)習(xí)過程,對于該游戲案例的制作過程并不十分詳盡,不作為教程使用,僅用于自己學(xué)習(xí)參考,記錄于此,聊表心意。
★★黃色加速小鳥(繼承自紅色)
基本思路,在紅色小鳥的腳本中添加是否處于飛行中的判斷,具體做法是,聲明一個bool變量isfly,初始值為false,在鼠標(biāo)按下調(diào)用飛行函數(shù)的時候,設(shè)置值為true,在小鳥碰撞檢測的函數(shù)中設(shè)置為false。
然后添加一個釋放技能函數(shù)showskill,在update中,在雙重判斷下執(zhí)行(是否處于飛行中,和是否按下了鼠標(biāo)左鍵),showskill函數(shù)中首先寫上將isfly值改為false,以保證只能釋放一次技能。
? ? public virtual void ShowSkill() {
? ? ? ? isFly = false;
? ? }
為了繼承,將釋放技能函數(shù)設(shè)置為虛函數(shù),并將Rigidbody2D屬性設(shè)置為保護(hù),以便子類中調(diào)用。
子類的設(shè)置,新建腳本,繼承birds,重寫showskill函數(shù),先調(diào)用基類的函數(shù),然后將速度設(shè)置為原來的兩倍。
? ? public override void ShowSkill()
? ? {
? ? ? ? base.ShowSkill();
? ? ? ? rg.velocity *= 2;
? ? }
新的黃色小鳥添加腳本后,需要在面板中重新賦值。
★★綠色回旋小鳥
方法同黃色,只是技能代碼不同
? ? public override void ShowSkill()
? ? {
? ? ? ? base.ShowSkill();
? ? ? ? Vector3 speed = rg.velocity;
? ? ? ? speed.x *= -1;
? ? ? ? rg.velocity = speed;
? ? }
★★小鳥受傷
與小豬受傷類似,先聲明
? ? private SpriteRenderer render;
? ? public Sprite hurt;
在awake中得到組件
? ? ? ? render = GetComponent<SpriteRenderer>();
在碰撞時改變圖集
? ? ? ? if (isShoot) {
? ? ? ? ? ? render.sprite = hurt;
? ? ? ? }
注意,這里為了避免一開始小鳥就受傷,所以用一個bool變量來標(biāo)記小鳥是否被發(fā)射出。
★★黑色爆炸小鳥
首先制作黑色小鳥
復(fù)制一個紅色的,改圖片,給賦值,去掉原來的代碼,加上黑色的代碼,再加一個碰撞器,注意勾選上觸發(fā)器trigger,改大些(爆炸范圍,碰到就死)。
然后來說代碼,用一個pig類型的表來裝在爆炸范圍內(nèi)的豬和木頭。
? ? public List<Pig> block = new List<Pig>();
? ??
? ? //進(jìn)入觸發(fā)區(qū)
? ? private void OnTriggerEnter2D(Collider2D collsion) {
? ? ? ? if (collsion.gameObject.tag == "Enemy") {
? ? ? ? ? ? block.Add(collsion.gameObject.GetComponent<Pig>());
? ? ? ? }
? ? }
? ? //出觸發(fā)區(qū)
? ? private void OnTriggerExit2D(Collider2D collsion) {
? ? ? ? if (collsion.gameObject.tag == "Enemy")
? ? ? ? {
? ? ? ? ? ? block.Remove(collsion.gameObject.GetComponent<Pig>());
? ? ? ? }
? ? }
其中,用標(biāo)簽類識別敵人。
在技能釋放中銷毀這些物體。
? ? ? ? while (block.Count > 0 && block != null) {
? ? ? ? ? ? block[0].PigDead();
? ? ? ? }
★注意【foreach循環(huán)中是能對list集合進(jìn)行讀取,而不能去銷毀表中的內(nèi)容。】
【for循環(huán)會記錄當(dāng)前讀取到的下標(biāo)位置,而物體銷毀掉后,剩余物體在表中的位置會發(fā)生變化,導(dǎo)致銷毀不完全。】
黑鳥爆炸后,原地隱藏,及后事處理。
? ? void OnClear() {
? ? ? ? rg.velocity = Vector3.zero;
? ? ? ? Instantiate(boom, transform.position, Quaternion.identity);
? ? ? ? render.enabled = false;
? ? ? ? GetComponent<CircleCollider2D>().enabled = false;
? ? }
其中,包括對小鳥速度的設(shè)置(剛體速度設(shè)為0,小鳥不再動),生成爆炸預(yù)制體,不再渲染顯示,取消激活其碰撞體。
重寫銷毀方法,只需去掉生成爆炸預(yù)制體。
? ? protected override void DestoryBird()
? ? {
? ? ? ? GameManager._instance.birds.Remove(this);
? ? ? ? Destroy(gameObject);
? ? ? ? GameManager._instance.NextBird();
? ? }
★★場景補(bǔ)全
★★好吧從這里開始要劃水水了
添加布置木頭和豬豬。
★★選擇地圖界面的UI
添加畫布,圖片。
可以更改畫布的尺寸。有三種UI尺寸模式。
★★地圖選擇實(shí)現(xiàn)
在每一個關(guān)卡地圖上,有鎖定和已激活兩個ui界面,同時只顯示一個。
為地圖UI添加代碼,添加一個變量(激活該關(guān)卡需要的星星數(shù)量),和一個標(biāo)志符(是否能激活),在start函數(shù)中寫,如果總星星數(shù)大于激活需要星星數(shù),則設(shè)置標(biāo)識符為已激活。繼續(xù)判斷是否激活,若激活則顯示星星數(shù)量UI,未激活顯示鎖定UI。
?? ?void Start () {
? ? ? ? if (PlayerPrefs.GetInt("totalStar", 0) >= starNum) {
? ? ? ? ? ? isSelect = true;
? ? ? ? }
? ? ? ? if (isSelect) {
? ? ? ? ? ? locks.SetActive(false);
? ? ? ? ? ? stars.SetActive(true);
? ? ? ? }
?? ?}
其中,鎖定UI和星星UI需要在編輯器賦值。總星星數(shù)用Unity提供的鍵值對存儲給出。
這樣在每一次進(jìn)入關(guān)卡選擇場景,都會判斷激活的地圖(根據(jù)事先確定好的限制星星數(shù)量)
★★關(guān)卡界面UI
多是一些圖集的設(shè)置,主要關(guān)鍵點(diǎn)是邏輯和層次關(guān)系要理清楚,在此簡述邏輯。
首先是空物體的關(guān)卡面板(下有如返回這樣的按鈕,空物體的關(guān)卡容器(加grid layout group組件對其內(nèi)的每個關(guān)卡進(jìn)行排布管理)),容器中裝統(tǒng)一的關(guān)卡圖標(biāo),每個關(guān)卡為一個圖集,其下還有要顯示用的關(guān)卡數(shù)字,獲得的星星。
代碼邏輯部分
? ? public bool isSelect = false;
? ? public Sprite levelBG;
? ? private Image image;
? ? void Awake() {
? ? ? ? image = GetComponent<Image>();
? ? }
?? ?void Start () {
? ? ? ? if (transform.parent.GetChild(0).name == gameObject.name) {
? ? ? ? ? ? isSelect = true;
? ? ? ? }
? ? ? ? if (isSelect) {
? ? ? ? ? ? image.overrideSprite = levelBG;
? ? ? ? ? ? transform.Find("num").gameObject.SetActive(true);
? ? ? ? }
?? ?}
其中,每個關(guān)卡都放上腳本,默認(rèn)時為顯示鎖圖標(biāo),在開始時對其判斷是否解鎖,每一個可以選擇的關(guān)卡,重寫圖片為激活狀態(tài)的圖片,將數(shù)字激活顯示,其中用第一個子物體名字相等確保第一關(guān)處于激活。
★★實(shí)現(xiàn)從地圖到關(guān)卡的選擇
在mapselect腳本中添加選擇事件,激活levelpanel的UI,隱藏map的UI。
? ? public GameObject panel;
? ? public GameObject map;
? ? public void Select() {
? ? ? ? if (isSelect) {
? ? ? ? ? ? panel.SetActive(true);
? ? ? ? ? ? map.SetActive(false);
? ? ? ? }
? ? }
其中,需要給不同的map賦上不同的值,map屬性的值都一樣,levelpanel的值則需對應(yīng)起來,并在每個map中都添加鼠標(biāo)點(diǎn)擊事件,分別調(diào)用各自的select函數(shù)。
★★游戲結(jié)束,星星數(shù)據(jù)的存儲
首先在關(guān)卡選擇處,選擇成功后,存儲當(dāng)前關(guān)卡信息。
? ? ? ? if (isSelect)
? ? ? ? {
? ? ? ? ? ? PlayerPrefs.SetString("newLevel", "level"+gameObject.name);
? ? ? ? }
在游戲管理類中,寫存儲信息函數(shù)。
? ? public void SaveData() {
? ? ? ? if (starNum > PlayerPrefs.GetInt(PlayerPrefs.GetString("nowLevel"), 0)) {
? ? ? ? ? ? PlayerPrefs.SetInt(PlayerPrefs.GetString("nowLevel"), starNum);
? ? ? ? }
? ? }
在游戲結(jié)束,顯示星星面板中,結(jié)算星星后調(diào)用存儲。
總星星數(shù)的存儲。
? ? ? ? int sum = 0;
? ? ? ? for (int i = 1; i <= totalStar; i++) {
? ? ? ? ? ? sum += PlayerPrefs.GetInt(PlayerPrefs.GetString("level" + i.ToString()));
? ? ? ? }
? ? ? ? PlayerPrefs.SetInt("totalStar", sum);
?? ?}
其中每次都從第一個關(guān)卡開始求和,計算出總數(shù)后存到totalStar中。
★★場景加載
將已制作好的游戲場景中的除了主攝像機(jī)都放到level01空物體下,制成預(yù)制體,類似的制作不同關(guān)卡的預(yù)制體,放到Resources資源目錄下,以備調(diào)用。
在主攝像機(jī)上掛載加載代碼。
? ? private void Awake() {
? ? ? ? Instantiate(Resources.Load(PlayerPrefs.GetString("nowLevel")));
? ? }
在關(guān)卡選擇時加載游戲場景。
? ? ? ? if (isSelect)
? ? ? ? {
? ? ? ? ? ? PlayerPrefs.SetString("nowLevel", "level"+gameObject.name);
? ? ? ? ? ? SceneManager.LoadScene(2);
? ? ? ? }
? ? }
并將其注冊到每一個關(guān)卡按鈕點(diǎn)擊事件中。
★★后續(xù)關(guān)卡的解鎖
在關(guān)卡選擇代碼中,在start函數(shù)中判斷了第一個關(guān)卡后,再判斷后面的的關(guān)卡是否可選
? ? ? ? if (transform.parent.GetChild(0).name == gameObject.name)
? ? ? ? {
? ? ? ? ? ? isSelect = true;
? ? ? ? }
? ? ? ? else {
? ? ? ? ? ? int beforeStar = int.Parse(gameObject.name) - 1;
? ? ? ? ? ? if (PlayerPrefs.GetInt("level" + beforeStar.ToString()) > 0) {
? ? ? ? ? ? ? ? isSelect = true;
? ? ? ? ? ? }
? ? ? ? }
其中,先獲得前一個關(guān)卡的星星數(shù)量,若果大于0則可以選則。
★★文本框中星星數(shù)量的實(shí)現(xiàn)。
? ? ? ? ? ? int counts = 0;
? ? ? ? ? ? for (int i = startLevel; i <= endLevel; i++) {
? ? ? ? ? ? ? ? counts += PlayerPrefs.GetInt("level" + i.ToString(), 0);
? ? ? ? ? ? }
? ? ? ? ? ? starText.text = counts.ToString() + "/20";
★★異步加載
?? ?void Start () {
? ? ? ? PlayerPrefs.DeleteAll();
? ? ? ? SceneManager.LoadSceneAsync(1);
?? ?}
★★完善與發(fā)布
★★bug修復(fù)
1,待定小鳥可以點(diǎn)擊的問題:將canMove屬性默認(rèn)為false,在初始化小鳥函數(shù)中再設(shè)置為true。
2,暫停時小鳥可以點(diǎn)擊的問題:個人覺得其解決方法不是很妥當(dāng),此處略去。
3,小鳥飛行中點(diǎn)擊暫停會釋放技能的問題:可以通過設(shè)置UI界面的【raycast target】屬性,不勾選可以不做交互,讓鼠標(biāo)點(diǎn)擊穿過這層UI。
總結(jié)
以上是生活随笔為你收集整理的siki学院_Unity初级案例_愤怒的小鸟_学习笔记3/3的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GeoJSON详解
- 下一篇: photoswipe.min.js 使用