Unity3D_(游戏)2D坦克大战 像素版
?
2D坦克大戰(zhàn)? ? 像素版
游戲規(guī)則:
玩家通過上、下、左、右移動(dòng)坦克,空格鍵發(fā)射子彈
敵人AI出身時(shí)朝向己方大本營(未防止游戲快速結(jié)束,心臟上方三個(gè)單位障礙物設(shè)為剛體)
當(dāng)玩家被擊殺次數(shù)>=3 或 心臟被子彈擊穿 重新加載游戲場景
控制游戲每4秒發(fā)射一顆子彈(可自己做修改)
?
游戲項(xiàng)目已托管到Github上 傳送門?
?
(文章最下邊有游戲腳本)
?
場景搭建
?
設(shè)置Main Camera攝像頭參數(shù)
?
?
游戲中制作預(yù)制體與動(dòng)畫
?
創(chuàng)建一個(gè)Cube作為參照,Cube長寬高都為1m
創(chuàng)建一個(gè)Player1_0作為玩家
? ? ?將Player1_0制作成預(yù)制體
?
制作游戲磚塊、鋼鐵、草叢、基地預(yù)制體
?
創(chuàng)建游戲物體出生動(dòng)畫Animation
快速創(chuàng)建動(dòng)畫:點(diǎn)擊第一張圖片->按住Shift->點(diǎn)擊最后一張圖片
保存好后場景出現(xiàn)Born_0動(dòng)畫,修改scale大小為3 3 3
?
?
制作坦克出生無敵、坦克爆炸、河流特效
動(dòng)畫大小與預(yù)制體適配
?
?
控制玩家的移動(dòng)
?
添加Player.cs腳本,綁定到Player玩家坦克上
?
默認(rèn)移動(dòng)速度
public float moveSpeed = 3;?
監(jiān)聽玩家水平軸輸入
float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1 transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);?
監(jiān)聽玩家垂直軸輸入
float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);?
?
?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Player : MonoBehaviour {public float moveSpeed = 3;// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {//監(jiān)聽玩家水平軸輸入float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);//監(jiān)聽玩家垂直軸輸入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);} } Player.cs?
?
控制圖片的移動(dòng)和切換
?
制作坦克渲染
添加精靈數(shù)組的引用
private SpriteRenderer sr;public Sprite[] tankSprite;?
(上 右 下 左)
?
玩家按上下左右控制坦克方向的移動(dòng)
//監(jiān)聽玩家水平軸輸入float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);if (h < 0){sr.sprite = tankSprite[3];}else if (h>0){sr.sprite = tankSprite[1];}//監(jiān)聽玩家垂直軸輸入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];}else if (v > 0){sr.sprite = tankSprite[0];}?
?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Player : MonoBehaviour {public float moveSpeed = 3;private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左// Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update () {//監(jiān)聽玩家水平軸輸入float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);if (h < 0){sr.sprite = tankSprite[3];}else if (h>0){sr.sprite = tankSprite[1];}//監(jiān)聽玩家垂直軸輸入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];}else if (v > 0){sr.sprite = tankSprite[0];}} } Player.cs?
?
碰撞器的添加
?
碰撞檢測
兩個(gè)物體都有碰撞器
一個(gè)物體上掛載剛體組件
?
給玩家Player添加2D剛體和2D碰撞器
剛體的Gravity Scale設(shè)置為0,取消重力因素的影響
?
? 給Barriar、Wall、River、Heart添加Box Collider 2D碰撞器
?
?
發(fā)現(xiàn)坦克方向坐標(biāo)軸會(huì)改變,在Rigidbody 2D中Constraints下的Freeze Rotation Z 進(jìn)行綁定,當(dāng)它碰撞到物體時(shí)坐標(biāo)不發(fā)生偏移
?
?
解決抖動(dòng)問題
?
使用private void FixedUpdate()
FixedUpdate () 和 Update () 同:當(dāng)MonoBehaviour啟用時(shí),其在每一幀被調(diào)用。都是用來更新的異:Update()每一幀的時(shí)間不固定,即第一幀與第二幀的時(shí)間t1和第三幀與第四幀的時(shí)間t2不一定相同。FixedUpdate()每幀與每幀之間相差的時(shí)間是固定的.Update受當(dāng)前渲染的物體影響,這與當(dāng)前場景中正在被渲染的物體有關(guān)(比如人物的面數(shù),個(gè)數(shù)等),有時(shí)快有時(shí)慢,幀率會(huì)變化,Update被調(diào)用的時(shí)間間隔就會(huì)發(fā)生變化。但是FixedUpdate則不受幀率的變化影響,它是以固定的時(shí)間間隔來被調(diào)用。所以一些物理屬性的更新操作應(yīng)該放在FxiedUpdate中操作,比如Force,Collider,Rigidbody等。外設(shè)的操作也是,比如說鍵盤或者鼠標(biāo)的輸入輸出Input,因?yàn)檫@樣GameObject的物理表現(xiàn)的更平滑,更接近現(xiàn)實(shí)。FixedUpdate的時(shí)間間隔可以在項(xiàng)目設(shè)置中更改,Edit->Project Setting->time 找到Fixed timestep。就可以修改了 FixedUpdate () 和 Update ()?
//監(jiān)聽玩家水平軸輸入float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1transform.Translate(Vector3.right*h*moveSpeed*Time.fixedDeltaTime,Space.World);//監(jiān)聽玩家垂直軸輸入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);?
FixedUpdate()方法留空就行
private void FixedUpdate(){}?
?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Player : MonoBehaviour {public float moveSpeed = 3;private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左// Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update () {//監(jiān)聽玩家水平軸輸入float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1transform.Translate(Vector3.right*h*moveSpeed*Time.fixedDeltaTime,Space.World);if (h < 0){sr.sprite = tankSprite[3];}else if (h>0){sr.sprite = tankSprite[1];}//監(jiān)聽玩家垂直軸輸入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];}else if (v > 0){sr.sprite = tankSprite[0];}}// private void FixedUpdate(){} } Player.cs?
解決玩家按方向鍵左右的同時(shí)按上下
在監(jiān)聽玩家垂直軸輸入后對(duì)v方向按鍵進(jìn)行判斷,如果為0則在Update()中直接返回
float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];}else if (v > 0){sr.sprite = tankSprite[0];}if(v!=0){return;}//監(jiān)聽玩家水平軸輸入float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1transform.Translate(Vector3.right*h*moveSpeed*Time.fixedDeltaTime,Space.World);if (h < 0){sr.sprite = tankSprite[3];}else if (h>0){sr.sprite = tankSprite[1];}?
整理一下Player.cs腳本
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Player : MonoBehaviour {//屬性值public float moveSpeed = 3;//引用private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左// Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update () {}private void FixedUpdate(){Move();}//坦克的移動(dòng)方法private void Move(){//監(jiān)聽玩家垂直軸輸入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];}else if (v > 0){sr.sprite = tankSprite[0];}if (v != 0){return;}//監(jiān)聽玩家水平軸輸入float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);if (h < 0){sr.sprite = tankSprite[3];}else if (h > 0){sr.sprite = tankSprite[1];}} } Player.cs?
?
2D渲染層級(jí)
?
設(shè)置游戲物體的層級(jí)
?
?
?
?
坦克的攻擊
?
坦克的攻擊方法
private void Attack(){if(Input.GetKeyDown(KeyCode.Space)){Instantiate(bullectPrefab,transform.position,transform.rotation);}}?
private void FixedUpdate(){Move();Attack();}?
?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Player : MonoBehaviour {//屬性值public float moveSpeed = 3;//引用private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左public GameObject bullectPrefab;// Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update () {}private void FixedUpdate(){Move();Attack();}//坦克的攻擊方法private void Attack(){if(Input.GetKeyDown(KeyCode.Space)){Instantiate(bullectPrefab,transform.position,transform.rotation);}}//坦克的移動(dòng)方法private void Move(){//監(jiān)聽玩家垂直軸輸入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];}else if (v > 0){sr.sprite = tankSprite[0];}if (v != 0){return;}//監(jiān)聽玩家水平軸輸入float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);if (h < 0){sr.sprite = tankSprite[3];}else if (h > 0){sr.sprite = tankSprite[1];}} } player.cs?
子彈的朝向和移動(dòng)
通過按鍵V和H來判斷子彈旋轉(zhuǎn)的角度
?
定義子彈旋轉(zhuǎn)的角度
private Vector3 bullectEulerAugles;?
子彈參數(shù)的角度:當(dāng)前坦克的角度+子彈應(yīng)該旋轉(zhuǎn)的角度
Instantiate(bullectPrefab,transform.position,Quaternion.Euler(transform.eulerAngles+bullectEulerAugles));?
---恢復(fù)內(nèi)容結(jié)束---
?
?
未完~
?
完成時(shí)會(huì)有完整項(xiàng)目展示
?
?
場景搭建
?
設(shè)置Main Camera攝像頭參數(shù)
?
?
游戲中制作預(yù)制體與動(dòng)畫
?
創(chuàng)建一個(gè)Cube作為參照,Cube長寬高都為1m
創(chuàng)建一個(gè)Player1_0作為玩家
? ? ?將Player1_0制作成預(yù)制體
?
制作游戲磚塊、鋼鐵、草叢、基地預(yù)制體
?
創(chuàng)建游戲物體出生動(dòng)畫Animation
快速創(chuàng)建動(dòng)畫:點(diǎn)擊第一張圖片->按住Shift->點(diǎn)擊最后一張圖片
保存好后場景出現(xiàn)Born_0動(dòng)畫,修改scale大小為3 3 3
?
?
制作坦克出生無敵、坦克爆炸、河流特效
動(dòng)畫大小與預(yù)制體適配
?
?
控制玩家的移動(dòng)
?
添加Player.cs腳本,綁定到Player玩家坦克上
?
默認(rèn)移動(dòng)速度
public float moveSpeed = 3;?
監(jiān)聽玩家水平軸輸入
float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1 transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);?
監(jiān)聽玩家垂直軸輸入
float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);?
?
?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Player : MonoBehaviour {public float moveSpeed = 3;// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {//監(jiān)聽玩家水平軸輸入float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);//監(jiān)聽玩家垂直軸輸入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);} } Player.cs?
?
控制圖片的移動(dòng)和切換
?
制作坦克渲染
添加精靈數(shù)組的引用
private SpriteRenderer sr;public Sprite[] tankSprite;?
(上 右 下 左)
?
玩家按上下左右控制坦克方向的移動(dòng)
//監(jiān)聽玩家水平軸輸入float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);if (h < 0){sr.sprite = tankSprite[3];}else if (h>0){sr.sprite = tankSprite[1];}//監(jiān)聽玩家垂直軸輸入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];}else if (v > 0){sr.sprite = tankSprite[0];}?
?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Player : MonoBehaviour {public float moveSpeed = 3;private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左// Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update () {//監(jiān)聽玩家水平軸輸入float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);if (h < 0){sr.sprite = tankSprite[3];}else if (h>0){sr.sprite = tankSprite[1];}//監(jiān)聽玩家垂直軸輸入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];}else if (v > 0){sr.sprite = tankSprite[0];}} } Player.cs?
?
碰撞器的添加
?
碰撞檢測
兩個(gè)物體都有碰撞器
一個(gè)物體上掛載剛體組件
?
給玩家Player添加2D剛體和2D碰撞器
剛體的Gravity Scale設(shè)置為0,取消重力因素的影響
?
? 給Barriar、Wall、River、Heart添加Box Collider 2D碰撞器
?
?
發(fā)現(xiàn)坦克方向坐標(biāo)軸會(huì)改變,在Rigidbody 2D中Constraints下的Freeze Rotation Z 進(jìn)行綁定,當(dāng)它碰撞到物體時(shí)坐標(biāo)不發(fā)生偏移
?
?
解決抖動(dòng)問題
?
使用private void FixedUpdate()
FixedUpdate () 和 Update () 同:當(dāng)MonoBehaviour啟用時(shí),其在每一幀被調(diào)用。都是用來更新的異:Update()每一幀的時(shí)間不固定,即第一幀與第二幀的時(shí)間t1和第三幀與第四幀的時(shí)間t2不一定相同。FixedUpdate()每幀與每幀之間相差的時(shí)間是固定的.Update受當(dāng)前渲染的物體影響,這與當(dāng)前場景中正在被渲染的物體有關(guān)(比如人物的面數(shù),個(gè)數(shù)等),有時(shí)快有時(shí)慢,幀率會(huì)變化,Update被調(diào)用的時(shí)間間隔就會(huì)發(fā)生變化。但是FixedUpdate則不受幀率的變化影響,它是以固定的時(shí)間間隔來被調(diào)用。所以一些物理屬性的更新操作應(yīng)該放在FxiedUpdate中操作,比如Force,Collider,Rigidbody等。外設(shè)的操作也是,比如說鍵盤或者鼠標(biāo)的輸入輸出Input,因?yàn)檫@樣GameObject的物理表現(xiàn)的更平滑,更接近現(xiàn)實(shí)。FixedUpdate的時(shí)間間隔可以在項(xiàng)目設(shè)置中更改,Edit->Project Setting->time 找到Fixed timestep。就可以修改了 FixedUpdate () 和 Update ()?
//監(jiān)聽玩家水平軸輸入float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1transform.Translate(Vector3.right*h*moveSpeed*Time.fixedDeltaTime,Space.World);//監(jiān)聽玩家垂直軸輸入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);?
FixedUpdate()方法留空就行
private void FixedUpdate(){}?
?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Player : MonoBehaviour {public float moveSpeed = 3;private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左// Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update () {//監(jiān)聽玩家水平軸輸入float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1transform.Translate(Vector3.right*h*moveSpeed*Time.fixedDeltaTime,Space.World);if (h < 0){sr.sprite = tankSprite[3];}else if (h>0){sr.sprite = tankSprite[1];}//監(jiān)聽玩家垂直軸輸入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];}else if (v > 0){sr.sprite = tankSprite[0];}}// private void FixedUpdate(){} } Player.cs?
解決玩家按方向鍵左右的同時(shí)按上下
在監(jiān)聽玩家垂直軸輸入后對(duì)v方向按鍵進(jìn)行判斷,如果為0則在Update()中直接返回
float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];}else if (v > 0){sr.sprite = tankSprite[0];}if(v!=0){return;}//監(jiān)聽玩家水平軸輸入float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1transform.Translate(Vector3.right*h*moveSpeed*Time.fixedDeltaTime,Space.World);if (h < 0){sr.sprite = tankSprite[3];}else if (h>0){sr.sprite = tankSprite[1];}?
整理一下Player.cs腳本
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Player : MonoBehaviour {//屬性值public float moveSpeed = 3;//引用private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左// Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update () {}private void FixedUpdate(){Move();}//坦克的移動(dòng)方法private void Move(){//監(jiān)聽玩家垂直軸輸入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];}else if (v > 0){sr.sprite = tankSprite[0];}if (v != 0){return;}//監(jiān)聽玩家水平軸輸入float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);if (h < 0){sr.sprite = tankSprite[3];}else if (h > 0){sr.sprite = tankSprite[1];}} } Player.cs?
?
2D渲染層級(jí)
?
設(shè)置游戲物體的層級(jí)
?
?
?
?
坦克的攻擊
?
坦克的攻擊方法
private void Attack(){if(Input.GetKeyDown(KeyCode.Space)){Instantiate(bullectPrefab,transform.position,transform.rotation);}}?
private void FixedUpdate(){Move();Attack();}?
?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Player : MonoBehaviour {//屬性值public float moveSpeed = 3;//引用private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左public GameObject bullectPrefab;// Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update () {}private void FixedUpdate(){Move();Attack();}//坦克的攻擊方法private void Attack(){if(Input.GetKeyDown(KeyCode.Space)){Instantiate(bullectPrefab,transform.position,transform.rotation);}}//坦克的移動(dòng)方法private void Move(){//監(jiān)聽玩家垂直軸輸入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];}else if (v > 0){sr.sprite = tankSprite[0];}if (v != 0){return;}//監(jiān)聽玩家水平軸輸入float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);if (h < 0){sr.sprite = tankSprite[3];}else if (h > 0){sr.sprite = tankSprite[1];}} } player.cs?
子彈的朝向和移動(dòng)
通過按鍵V和H來判斷子彈旋轉(zhuǎn)的角度
?
定義子彈旋轉(zhuǎn)的角度
private Vector3 bullectEulerAugles;?
子彈參數(shù)的角度:當(dāng)前坦克的角度+子彈應(yīng)該旋轉(zhuǎn)的角度
Instantiate(bullectPrefab,transform.position,Quaternion.Euler(transform.eulerAngles+bullectEulerAugles));?
private void Attack(){if(Input.GetKeyDown(KeyCode.Space)){//子彈參數(shù)的角度:當(dāng)前坦克的角度+子彈應(yīng)該旋轉(zhuǎn)的角度Instantiate(bullectPrefab,transform.position,Quaternion.Euler(transform.eulerAngles+bullectEulerAugles));timeVal = 0;}}?
給子彈添加方向速度
public float moveSpeed = 10;?
給子彈添加判斷是否是友軍
public bool isPlayerBullect;?
void Update () {transform.Translate(transform.up*moveSpeed*Time.deltaTime,Space.World);}?
添加子彈攻擊CD間隔
if (timeVal>=0.4f){//間隔大于0.4的時(shí)候才有攻擊效果 Attack();}else{timeVal += Time.deltaTime;}?
?
?
?
給組件添加標(biāo)簽
?
給子彈添加碰撞體和觸發(fā)器
?
添加Heart.cs腳本,當(dāng)Heart心臟被子彈攻擊時(shí),切換死亡圖片
private SpriteRenderer sr;public Sprite BrokenSprite; // Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}?
添加Heart.cs心臟死亡時(shí)方法
private void Die(){sr.sprite = BrokenSprite; }?
添加Explosion.cs腳本
當(dāng)坦克銷毀時(shí)觸發(fā)腳本
public class Explosion : MonoBehaviour {// Use this for initializationvoid Start () {//坦克銷毀后0.167秒銷毀爆炸特效Destroy(gameObject,0.167f);}// Update is called once per framevoid Update () {} }?
子彈觸發(fā)碰撞檢測
當(dāng)子彈碰撞到物體時(shí)觸發(fā)OnTriggerEnter2D(Collider2D collision)方法
子彈碰到“Tank”判斷是否是友軍,不是的話擊毀自己
子彈碰到"Wall"時(shí),銷毀子彈自身
子彈碰到"Heart"時(shí),觸發(fā)基地死亡方法
子彈碰到"Barrier"剛體時(shí),銷毀子彈
?
private void OnTriggerEnter2D(Collider2D collision){switch(collision.tag){case "Tank":if(!isPlayerBullect){collision.SendMessage("Die");}break;case "Heart":collision.SendMessage("Die");Destroy(gameObject);break;case "Enemy":break;case "Wall"://銷毀自身和墻 Destroy(collision.gameObject);Destroy(gameObject);break;case "Barrier":Destroy(gameObject);break;default:break;}}?
?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Player : MonoBehaviour {//屬性值public float moveSpeed = 3;private Vector3 bullectEulerAugles;public float timeVal;private float defendTimeVal=1;private bool isDefended=true;//引用private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左public GameObject bullectPrefab;public GameObject explosionPrefab;public GameObject defendEffectPrefab;// Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update () {//保護(hù)是否處于無敵狀態(tài)if(isDefended){defendEffectPrefab.SetActive(true);defendTimeVal -= Time.deltaTime;if (defendTimeVal<=0){isDefended = false;defendEffectPrefab.SetActive(false);}}//攻擊的CDif (timeVal>=0.4f){//間隔大于0.4的時(shí)候才有攻擊效果 Attack();}else{timeVal += Time.deltaTime;}}private void FixedUpdate(){Move();}//坦克的攻擊方法private void Attack(){if(Input.GetKeyDown(KeyCode.Space)){//子彈參數(shù)的角度:當(dāng)前坦克的角度+子彈應(yīng)該旋轉(zhuǎn)的角度Instantiate(bullectPrefab,transform.position,Quaternion.Euler(transform.eulerAngles+bullectEulerAugles));timeVal = 0;}}//坦克的移動(dòng)方法private void Move(){//監(jiān)聽玩家垂直軸輸入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];bullectEulerAugles = new Vector3(0, 0, -180);}else if (v > 0){sr.sprite = tankSprite[0];bullectEulerAugles = new Vector3(0, 0, 0);}if (v != 0){return;}//監(jiān)聽玩家水平軸輸入float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);if (h < 0){sr.sprite = tankSprite[3];bullectEulerAugles = new Vector3(0, 0, 90);}else if (h > 0){sr.sprite = tankSprite[1];bullectEulerAugles = new Vector3(0, 0, -90);}}//坦克的死亡方法private void Die(){if(isDefended){return;}//產(chǎn)生爆炸特效 Instantiate(explosionPrefab, transform.position, transform.rotation);//死亡 Destroy(gameObject);} } Player.cs?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Explosion : MonoBehaviour {// Use this for initializationvoid Start () {//坦克銷毀后0.167秒銷毀爆炸特效Destroy(gameObject,0.167f);}// Update is called once per framevoid Update () {} } Explosion.cs?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Heart : MonoBehaviour {private SpriteRenderer sr;public Sprite BrokenSprite; // Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}private void Die(){sr.sprite = BrokenSprite; } } Heart?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Bullect : MonoBehaviour {public float moveSpeed = 10;public bool isPlayerBullect;// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {transform.Translate(transform.up*moveSpeed*Time.deltaTime,Space.World);}//子彈觸發(fā)碰撞檢測private void OnTriggerEnter2D(Collider2D collision){switch(collision.tag){case "Tank":if(!isPlayerBullect){collision.SendMessage("Die");}break;case "Heart":collision.SendMessage("Die");Destroy(gameObject);break;case "Enemy":break;case "Wall"://銷毀自身和墻 Destroy(collision.gameObject);Destroy(gameObject);break;case "Barrier":Destroy(gameObject);break;default:break;}}} Bullect.cs?
?
敵人的制作
?
Ctrl+D一份玩家,修改圖片渲染,制作敵人
?
添加敵人腳本Enemy.cs
玩家的移動(dòng)和敵人的移動(dòng)差不多,把Player.cs腳本中內(nèi)容復(fù)制到Enemy.cs當(dāng)中
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Enemy : MonoBehaviour {//屬性值public float moveSpeed = 3;private Vector3 bullectEulerAugles;public float timeVal;private float defendTimeVal = 1;private bool isDefended = true;//引用private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左public GameObject bullectPrefab;public GameObject explosionPrefab;public GameObject defendEffectPrefab;// Use this for initializationvoid Start(){sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update(){//保護(hù)是否處于無敵狀態(tài)if (isDefended){defendEffectPrefab.SetActive(true);defendTimeVal -= Time.deltaTime;if (defendTimeVal <= 0){isDefended = false;defendEffectPrefab.SetActive(false);}}//攻擊的CDif (timeVal >= 0.4f){//間隔大于0.4的時(shí)候才有攻擊效果 Attack();}else{timeVal += Time.deltaTime;}}private void FixedUpdate(){Move();}//坦克的攻擊方法private void Attack(){if (Input.GetKeyDown(KeyCode.Space)){//子彈參數(shù)的角度:當(dāng)前坦克的角度+子彈應(yīng)該旋轉(zhuǎn)的角度Instantiate(bullectPrefab, transform.position, Quaternion.Euler(transform.eulerAngles + bullectEulerAugles));timeVal = 0;}}//坦克的移動(dòng)方法private void Move(){//監(jiān)聽玩家垂直軸輸入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];bullectEulerAugles = new Vector3(0, 0, -180);}else if (v > 0){sr.sprite = tankSprite[0];bullectEulerAugles = new Vector3(0, 0, 0);}if (v != 0){return;}//監(jiān)聽玩家水平軸輸入float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);if (h < 0){sr.sprite = tankSprite[3];bullectEulerAugles = new Vector3(0, 0, 90);}else if (h > 0){sr.sprite = tankSprite[1];bullectEulerAugles = new Vector3(0, 0, -90);}}//坦克的死亡方法private void Die(){if (isDefended){return;}//產(chǎn)生爆炸特效 Instantiate(explosionPrefab, transform.position, transform.rotation);//死亡 Destroy(gameObject);} } Enemy.cs
(因?yàn)閿橙藳]有出生無敵3s,運(yùn)行時(shí)無敵預(yù)制體defendEffectPrefab會(huì)出現(xiàn)報(bào)空)
?
添加基地死亡時(shí)動(dòng)畫
public GameObject explosionPrefab;?
private void Die(){sr.sprite = BrokenSprite;Instantiate(explosionPrefab,transform.position,transform.rotation);}?
(關(guān)閉項(xiàng)目后爆炸腳本失活了,最后的時(shí)候再做一個(gè)補(bǔ)上)
?
添加一個(gè)玩家出生時(shí)腳本Born.cs
延時(shí)玩家出生和死亡動(dòng)畫
public GameObject playerPrefab;// Use this for initializationvoid Start () {Invoke("BornTank",1f);Destroy(gameObject,1f);}private void BornTank(){Instantiate(playerPrefab,transform.position,Quaternion.identity);}?
?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Born : MonoBehaviour {public GameObject playerPrefab;// Use this for initializationvoid Start () {Invoke("BornTank",0.8f);Destroy(gameObject,0.8f);}// Update is called once per framevoid Update () {}private void BornTank(){Instantiate(playerPrefab,transform.position,Quaternion.identity);} } Born.cs?
制作大坦克和小坦克,添加坦克方向變化時(shí)改變坦克方向圖片
坦克改變方向順序按上、右、下、左進(jìn)行添加
?
小敵人同打敵人設(shè)置當(dāng)坦克方向改變時(shí)切換自身圖片
將大敵人和小敵人設(shè)置成預(yù)制體
小敵人速度調(diào)大一些,改為5
?
編寫B(tài)orn.cs腳本判斷是否產(chǎn)生敵人
public bool createPlay;?
private void BornTank(){if (createPlay){Instantiate(playerPrefab, transform.position, Quaternion.identity);}else{int num = Random.Range(0, 2);Instantiate(enemyPrefabList[num], transform.position, Quaternion.identity);}}?
?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Born : MonoBehaviour {public GameObject playerPrefab;public GameObject[] enemyPrefabList;//判斷是否產(chǎn)生敵人public bool createPlay;// Use this for initializationvoid Start () {Invoke("BornTank",1f);Destroy(gameObject,1f);}private void Update(){}private void BornTank(){if (createPlay){Instantiate(playerPrefab, transform.position, Quaternion.identity);}else{int num = Random.Range(0, 2);Instantiate(enemyPrefabList[num], transform.position, Quaternion.identity);}} } Born.cs?
?
編寫敵人AI
?
子彈間3s攻擊一次
void Update(){//攻擊的時(shí)間間隔if (timeVal >= 0.3f){//間隔大于0.4的時(shí)候才有攻擊效果 Attack();}else{timeVal += Time.deltaTime;}}?
//坦克的攻擊方法private void Attack(){//子彈參數(shù)的角度:當(dāng)前坦克的角度+子彈應(yīng)該旋轉(zhuǎn)的角度Instantiate(bullectPrefab, transform.position, Quaternion.Euler(transform.eulerAngles + bullectEulerAugles));timeVal = 0;}?
坦克的移動(dòng)不需要按下上下左右鍵盤,只需要管理V和H的值對(duì)敵人AI進(jìn)行方向的控制
定義兩個(gè)計(jì)時(shí)器
public float timeVal;public float timeValChangeDirection;?
修改敵人移動(dòng)的方法
private void Move(){if(timeValChangeDirection>=4){int num = Random.Range(0,8);if(num>5){v = -1;h = 0;}else if (num == 0){v = 1;h = 0;}else if (num > 0 && num <= 2){h = -1;v = 0;}else if (num > 2 && num <= 4){h = 1;v = 0;}timeValChangeDirection = 0;}else{timeValChangeDirection += Time.fixedDeltaTime;}//監(jiān)聽玩家垂直軸輸入 transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];bullectEulerAugles = new Vector3(0, 0, -180);}else if (v > 0){sr.sprite = tankSprite[0];bullectEulerAugles = new Vector3(0, 0, 0);}if (v != 0){return;}//監(jiān)聽玩家水平軸輸入 transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);if (h < 0){sr.sprite = tankSprite[3];bullectEulerAugles = new Vector3(0, 0, 90);}else if (h > 0){sr.sprite = tankSprite[1];bullectEulerAugles = new Vector3(0, 0, -90);}}
?
?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Enemy : MonoBehaviour {//屬性值public float moveSpeed = 3;private Vector3 bullectEulerAugles;private float v;private float h;//引用private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左public GameObject bullectPrefab;public GameObject explosionPrefab;//計(jì)時(shí)器public float timeVal;public float timeValChangeDirection=4;// Use this for initializationvoid Start(){sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update(){//攻擊的時(shí)間間隔if (timeVal >= 0.3f){//間隔大于0.4的時(shí)候才有攻擊效果 Attack();}else{timeVal += Time.deltaTime;}}private void FixedUpdate(){Move();}//坦克的攻擊方法private void Attack(){//子彈參數(shù)的角度:當(dāng)前坦克的角度+子彈應(yīng)該旋轉(zhuǎn)的角度Instantiate(bullectPrefab, transform.position, Quaternion.Euler(transform.eulerAngles + bullectEulerAugles));timeVal = 0;}//坦克的移動(dòng)方法private void Move(){if(timeValChangeDirection>=4){int num = Random.Range(0,8);if(num>5){v = -1;h = 0;}else if (num == 0){v = 1;h = 0;}else if (num > 0 && num <= 2){h = -1;v = 0;}else if (num > 2 && num <= 4){h = 1;v = 0;}timeValChangeDirection = 0;}else{timeValChangeDirection += Time.fixedDeltaTime;}//監(jiān)聽玩家垂直軸輸入 transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];bullectEulerAugles = new Vector3(0, 0, -180);}else if (v > 0){sr.sprite = tankSprite[0];bullectEulerAugles = new Vector3(0, 0, 0);}if (v != 0){return;}//監(jiān)聽玩家水平軸輸入 transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);if (h < 0){sr.sprite = tankSprite[3];bullectEulerAugles = new Vector3(0, 0, 90);}else if (h > 0){sr.sprite = tankSprite[1];bullectEulerAugles = new Vector3(0, 0, -90);}}//坦克的死亡方法private void Die(){//產(chǎn)生爆炸特效 Instantiate(explosionPrefab, transform.position, transform.rotation);//死亡 Destroy(gameObject);} } Enemy.cs?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Bullect : MonoBehaviour {public float moveSpeed = 10;public bool isPlayerBullect;// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {transform.Translate(transform.up*moveSpeed*Time.deltaTime,Space.World);}//子彈觸發(fā)碰撞檢測private void OnTriggerEnter2D(Collider2D collision){switch(collision.tag){case "Tank":if(!isPlayerBullect){collision.SendMessage("Die");}Destroy(gameObject);break;case "Heart":collision.SendMessage("Die");Destroy(gameObject);break;case "Enemy":if(isPlayerBullect){collision.SendMessage("Die");}Destroy(gameObject);break;case "Wall"://銷毀自身和墻 Destroy(collision.gameObject);Destroy(gameObject);break;case "Barrier":Destroy(gameObject);break;default:break;}}} Bullect.cs?
?
初始化地圖工具
?
判斷地圖長度
?
地圖大小:長20 寬16
?
添加MapCreation.cs地圖管理器來控制草和地圖等建筑物
public class MapCreation : MonoBehaviour {//用來裝飾初始化地圖所需物體的數(shù)組//0.老家 1.墻 2.障礙 3.出生效果 4.河流 5.草 6.空氣墻public GameObject[] item;}?
?
制作老家心臟和心臟周圍的圍墻
private void Awake(){//實(shí)例化老家Instantiate(item[0], new Vector3(0, -8, -0), Quaternion.identity);//用墻把老家圍起來Instantiate(item[1], new Vector3(-1, -8, -0), Quaternion.identity);Instantiate(item[1], new Vector3(1, -8, -0), Quaternion.identity);for(int i=-1;i<2;i++){Instantiate(item[1],new Vector3(i,-7,0),Quaternion.identity);}}?
?
對(duì)同一個(gè)位置上進(jìn)行判斷,判斷是否有障礙物在上面,如果在上面那不再額外生成其它建筑物
已經(jīng)有東西位置的列表
private List<Vector3> itemPositionList = new List<Vector3>();?
private void CreateItem(GameObject createGameObject,Vector3 createPosition,Quaternion createRotate){GameObject itemGo = Instantiate(createGameObject, createPosition, createRotate);itemGo.transform.SetParent(gameObject.transform);itemPositionList.Add(createPosition);}?
制作外圍墻,也就是游戲邊界
for(int i=-11;i<12;i++){CreateItem(item[6], new Vector3(i, 9, 0), Quaternion.identity);}for(int i=-11;i<12;i++){CreateItem(item[6], new Vector3(i, -9, 0), Quaternion.identity);}for(int i=-8;i<9;i++){CreateItem(item[6], new Vector3(-11, i, 0), Quaternion.identity);}for(int i=-8;i<9;i++){CreateItem(item[6], new Vector3(-11, i, 0), Quaternion.identity);}?
產(chǎn)生隨機(jī)位置的方法
private Vector3 CreateRamdomPosition(){//不生成x=-10,10的兩列,y=-8和8這兩行的位置while(true){Vector3 createPosition = new Vector3(Random.Range(-9, 10), Random.Range(-7, 8),0);if(!HasThePosition(createPosition)){return createPosition;}}}?
用來判斷位置列表中是否有這個(gè)位置
private bool HasThePosition(Vector3 createPos){for(int i=0;i<itemPositionList.Count;i++){if(createPos==itemPositionList[i]){return true;}}return false;}?
?
修復(fù)子彈觸發(fā)碰撞檢測
private void OnTriggerEnter2D(Collider2D collision){switch(collision.tag){case "Tank":if(!isPlayerBullect){collision.SendMessage("Die");Destroy(gameObject);}break;case "Heart":collision.SendMessage("Die");Destroy(gameObject);break;case "Enemy":if(isPlayerBullect){collision.SendMessage("Die");Destroy(gameObject);}break;case "Wall"://銷毀自身和墻 Destroy(collision.gameObject);Destroy(gameObject);break;case "Barrier":Destroy(gameObject);break;default:break;}}?
?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Bullect : MonoBehaviour {public float moveSpeed = 10;public bool isPlayerBullect;// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {transform.Translate(transform.up*moveSpeed*Time.deltaTime,Space.World);}//子彈觸發(fā)碰撞檢測private void OnTriggerEnter2D(Collider2D collision){switch(collision.tag){case "Tank":if(!isPlayerBullect){collision.SendMessage("Die");Destroy(gameObject);}break;case "Heart":collision.SendMessage("Die");Destroy(gameObject);break;case "Enemy":if(isPlayerBullect){collision.SendMessage("Die");Destroy(gameObject);}break;case "Wall"://銷毀自身和墻 Destroy(collision.gameObject);Destroy(gameObject);break;case "Barrier":Destroy(gameObject);break;default:break;}}} Bullect.cs?
實(shí)例化地圖
for(int i=0;i<20;i++){CreateItem(item[1], CreateRamdomPosition(), Quaternion.identity);}for(int i=0;i<20;i++){CreateItem(item[2], CreateRamdomPosition(), Quaternion.identity);}for (int i = 0; i < 20; i++){CreateItem(item[4], CreateRamdomPosition(), Quaternion.identity);}for (int i = 0; i < 20; i++){CreateItem(item[5], CreateRamdomPosition(), Quaternion.identity);}?
?
初始化玩家
GameObject go = Instantiate(item[3], new Vector3(-2, -8, 0), Quaternion.identity); go.GetComponent<Born>().createPlay = true;?
產(chǎn)生敵人
CreateItem(item[3], new Vector3(-10,8,0),Quaternion.identity); CreateItem(item[3], new Vector3(0, 8, 0), Quaternion.identity); CreateItem(item[3], new Vector3(10, 8, 0), Quaternion.identity);?
實(shí)例化地圖并且讓圍墻的數(shù)量盡可能的多
for (int i=0;i<60;i++){CreateItem(item[1], CreateRamdomPosition(), Quaternion.identity);}for(int i=0;i<20;i++){CreateItem(item[2], CreateRamdomPosition(), Quaternion.identity);}for (int i = 0; i < 20; i++){CreateItem(item[4], CreateRamdomPosition(), Quaternion.identity);}for (int i = 0; i < 20; i++){CreateItem(item[5], CreateRamdomPosition(), Quaternion.identity);}?
產(chǎn)生敵人的方法
private void CreateEnemy(){int num = Random.Range(0, 3);Vector3 EnemyPos = new Vector3();if(num==0){EnemyPos = new Vector3(-10, 8, 0);}else if(num==1){EnemyPos = new Vector3(0, 8, 0);}else{EnemyPos = new Vector3(10, 8, 0);}CreateItem(item[3],EnemyPos,Quaternion.identity);}?
每隔5s產(chǎn)生一波敵人
InvokeRepeating("CreateEnemy",4,5);?
優(yōu)化一下敵人AI
敵人AI碰到一起時(shí)切換一次方向
private void OnCollisionEnter2D(Collision2D collision){if(collision.gameObject.tag=="Enemy"){timeValChangeDirection = 4;}}?
?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Player : MonoBehaviour {//屬性值public float moveSpeed = 3;private Vector3 bullectEulerAugles;public float timeVal;private float defendTimeVal=3;private bool isDefended=true;//引用private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左public GameObject bullectPrefab;public GameObject explosionPrefab;public GameObject defendEffectPrefab;// Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update () {//保護(hù)是否處于無敵狀態(tài)if(isDefended){defendEffectPrefab.SetActive(true);defendTimeVal -= Time.deltaTime;if (defendTimeVal<=0){isDefended = false;defendEffectPrefab.SetActive(false);}}//攻擊的CDif (timeVal>=0.4f){//間隔大于0.4的時(shí)候才有攻擊效果 Attack();}else{timeVal += Time.deltaTime;}}private void FixedUpdate(){Move();}//坦克的攻擊方法private void Attack(){if(Input.GetKeyDown(KeyCode.Space)){//子彈參數(shù)的角度:當(dāng)前坦克的角度+子彈應(yīng)該旋轉(zhuǎn)的角度Instantiate(bullectPrefab,transform.position,Quaternion.Euler(transform.eulerAngles+bullectEulerAugles));timeVal = 0;}}//坦克的移動(dòng)方法private void Move(){//監(jiān)聽玩家垂直軸輸入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];bullectEulerAugles = new Vector3(0, 0, -180);}else if (v > 0){sr.sprite = tankSprite[0];bullectEulerAugles = new Vector3(0, 0, 0);}if (v != 0){return;}//監(jiān)聽玩家水平軸輸入float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);if (h < 0){sr.sprite = tankSprite[3];bullectEulerAugles = new Vector3(0, 0, 90);}else if (h > 0){sr.sprite = tankSprite[1];bullectEulerAugles = new Vector3(0, 0, -90);}}//坦克的死亡方法private void Die(){if(isDefended){return;}//產(chǎn)生爆炸特效 Instantiate(explosionPrefab, transform.position, transform.rotation);//死亡 Destroy(gameObject);} } Player.cs?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class MapCreation : MonoBehaviour {//用來裝飾初始化地圖所需物體的數(shù)組//0.老家 1.墻 2.障礙 3.出生效果 4.河流 5.草 6.空氣墻public GameObject[] item;//已經(jīng)有東西位置的列表private List<Vector3> itemPositionList = new List<Vector3>();private void Awake(){//實(shí)例化老家CreateItem(item[0], new Vector3(0, -8, -0), Quaternion.identity);//用墻把老家圍起來CreateItem(item[1], new Vector3(-1, -8, -0), Quaternion.identity);CreateItem(item[1], new Vector3(1, -8, -0), Quaternion.identity);for(int i=-1;i<2;i++){Instantiate(item[1],new Vector3(i,-7,0),Quaternion.identity);}//實(shí)例化外圍墻for(int i=-11;i<12;i++){CreateItem(item[6], new Vector3(i, 9, 0), Quaternion.identity);}for(int i=-11;i<12;i++){CreateItem(item[6], new Vector3(i, -9, 0), Quaternion.identity);}for(int i=-8;i<9;i++){CreateItem(item[6], new Vector3(-11, i, 0), Quaternion.identity);}for(int i=-8;i<9;i++){CreateItem(item[6], new Vector3(11, i, 0), Quaternion.identity);}//初始化玩家GameObject go = Instantiate(item[3], new Vector3(-2, -8, 0), Quaternion.identity);go.GetComponent<Born>().createPlay = true;//產(chǎn)生敵人CreateItem(item[3], new Vector3(-10,8,0),Quaternion.identity);CreateItem(item[3], new Vector3(0, 8, 0), Quaternion.identity);CreateItem(item[3], new Vector3(10, 8, 0), Quaternion.identity);//第一次調(diào)用CreateEnemy用4s,每隔5s開調(diào)用InvokeRepeating("CreateEnemy",4,5);//實(shí)例化地圖for (int i=0;i<60;i++){CreateItem(item[1], CreateRamdomPosition(), Quaternion.identity);}for(int i=0;i<20;i++){CreateItem(item[2], CreateRamdomPosition(), Quaternion.identity);}for (int i = 0; i < 20; i++){CreateItem(item[4], CreateRamdomPosition(), Quaternion.identity);}for (int i = 0; i < 20; i++){CreateItem(item[5], CreateRamdomPosition(), Quaternion.identity);}}private void CreateItem(GameObject createGameObject,Vector3 createPosition,Quaternion createRotate){GameObject itemGo = Instantiate(createGameObject, createPosition, createRotate);itemGo.transform.SetParent(gameObject.transform);itemPositionList.Add(createPosition);}//產(chǎn)生隨機(jī)位置的方法private Vector3 CreateRamdomPosition(){//不生成x=-10,10的兩列,y=-8和8這兩行的位置while(true){Vector3 createPosition = new Vector3(Random.Range(-9, 10), Random.Range(-7, 8),0);if(!HasThePosition(createPosition)){return createPosition;}}}//用來判斷位置列表中是否有這個(gè)位置private bool HasThePosition(Vector3 createPos){for(int i=0;i<itemPositionList.Count;i++){if(createPos==itemPositionList[i]){return true;}}return false;}//產(chǎn)生敵人的方法private void CreateEnemy(){int num = Random.Range(0, 3);Vector3 EnemyPos = new Vector3();if(num==0){EnemyPos = new Vector3(-10, 8, 0);}else if(num==1){EnemyPos = new Vector3(0, 8, 0);}else{EnemyPos = new Vector3(10, 8, 0);}CreateItem(item[3],EnemyPos,Quaternion.identity);}} MapCreation.cs?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Born : MonoBehaviour {public GameObject playerPrefab;public GameObject[] enemyPrefabList;//判斷是否產(chǎn)生敵人public bool createPlay;// Use this for initializationvoid Start () {Invoke("BornTank",1f);Destroy(gameObject,1f);}private void Update(){}private void BornTank(){if (createPlay){Instantiate(playerPrefab, transform.position, Quaternion.identity);}else{int num = Random.Range(0, 2);Instantiate(enemyPrefabList[num], transform.position, Quaternion.identity);}} } Born.cs?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Enemy : MonoBehaviour {//屬性值public float moveSpeed = 3;private Vector3 bullectEulerAugles;private float v;private float h;//引用private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左public GameObject bullectPrefab;public GameObject explosionPrefab;//計(jì)時(shí)器public float timeVal;public float timeValChangeDirection=4;// Use this for initializationvoid Start(){sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update(){//攻擊的時(shí)間間隔if (timeVal >= 0.3f){//間隔大于0.4的時(shí)候才有攻擊效果 Attack();}else{timeVal += Time.deltaTime;}}private void FixedUpdate(){Move();}//坦克的攻擊方法private void Attack(){//子彈參數(shù)的角度:當(dāng)前坦克的角度+子彈應(yīng)該旋轉(zhuǎn)的角度Instantiate(bullectPrefab, transform.position, Quaternion.Euler(transform.eulerAngles + bullectEulerAugles));timeVal = 0;}//坦克的移動(dòng)方法private void Move(){if(timeValChangeDirection>=4){int num = Random.Range(0,8);if(num>5){v = -1;h = 0;}else if (num == 0){v = 1;h = 0;}else if (num > 0 && num <= 2){h = -1;v = 0;}else if (num > 2 && num <= 4){h = 1;v = 0;}timeValChangeDirection = 0;}else{timeValChangeDirection += Time.fixedDeltaTime;}//監(jiān)聽玩家垂直軸輸入 transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];bullectEulerAugles = new Vector3(0, 0, -180);}else if (v > 0){sr.sprite = tankSprite[0];bullectEulerAugles = new Vector3(0, 0, 0);}if (v != 0){return;}//監(jiān)聽玩家水平軸輸入 transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);if (h < 0){sr.sprite = tankSprite[3];bullectEulerAugles = new Vector3(0, 0, 90);}else if (h > 0){sr.sprite = tankSprite[1];bullectEulerAugles = new Vector3(0, 0, -90);}}//坦克的死亡方法private void Die(){//產(chǎn)生爆炸特效 Instantiate(explosionPrefab, transform.position, transform.rotation);//死亡 Destroy(gameObject);}//優(yōu)化敵人AIprivate void OnCollisionEnter2D(Collision2D collision){if(collision.gameObject.tag=="Enemy"){timeValChangeDirection = 4;}}} Enemy.cs?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Explosion : MonoBehaviour {// Use this for initializationvoid Start () {//坦克銷毀后0.167秒銷毀爆炸特效Destroy(gameObject,0.167f);}// Update is called once per framevoid Update () {} } Explosion?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Heart : MonoBehaviour {private SpriteRenderer sr;public GameObject explosionPrefab;public Sprite BrokenSprite; // Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}private void Die(){sr.sprite = BrokenSprite;Instantiate(explosionPrefab,transform.position,transform.rotation);} } Heart.cs?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Bullect : MonoBehaviour {public float moveSpeed = 10;public bool isPlayerBullect;// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {transform.Translate(transform.up*moveSpeed*Time.deltaTime,Space.World);}//子彈觸發(fā)碰撞檢測private void OnTriggerEnter2D(Collider2D collision){switch(collision.tag){case "Tank":if(!isPlayerBullect){collision.SendMessage("Die");Destroy(gameObject);}break;case "Heart":collision.SendMessage("Die");Destroy(gameObject);break;case "Enemy":if(isPlayerBullect){collision.SendMessage("Die");Destroy(gameObject);}break;case "Wall"://銷毀自身和墻 Destroy(collision.gameObject);Destroy(gameObject);break;case "Barrier":Destroy(gameObject);break;default:break;}}} Bullect.cs?
?
玩家狀態(tài)管理
?
游戲中添加空物體PlayerManager對(duì)象
添加游戲的屬性值
public int lifeVale = 3;public int playerScore = 0;public bool isDead;?
坦克的死亡方法
private void Die(){if(isDefended){return;}PlayerManager.Instance.isDead = true;//產(chǎn)生爆炸特效 Instantiate(explosionPrefab, transform.position, transform.rotation);//死亡 Destroy(gameObject);}?
玩家狀態(tài)管理類監(jiān)聽玩家狀態(tài),當(dāng)玩家被子彈擊中時(shí),生命值開始降低
void Update () {if(isDead){Recover();}}private void Recover(){if (lifeVale < 0){//游戲失敗,返回主界面 SceneManager.LoadScene("Game");}else{lifeVale--;GameObject go = Instantiate(born,new Vector3(-2,-8,0),Quaternion.identity);go.GetComponent<Born>().createPlay = true;isDead = false;}}?
?
?
游戲源代碼
?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Player : MonoBehaviour {//屬性值public float moveSpeed = 3;private Vector3 bullectEulerAugles;public float timeVal;private float defendTimeVal=3;private bool isDefended=true;//引用private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左public GameObject bullectPrefab;public GameObject explosionPrefab;public GameObject defendEffectPrefab;// Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update () {//保護(hù)是否處于無敵狀態(tài)if(isDefended){defendEffectPrefab.SetActive(true);defendTimeVal -= Time.deltaTime;if (defendTimeVal<=0){isDefended = false;defendEffectPrefab.SetActive(false);}}}private void FixedUpdate(){if(PlayerManager.Instance.isDefeat){return;}Move();//攻擊的CDif (timeVal >= 0.4f){//間隔大于0.4的時(shí)候才有攻擊效果 Attack();}else{timeVal += Time.fixedDeltaTime;}}//坦克的攻擊方法private void Attack(){if(Input.GetKeyDown(KeyCode.Space)){//子彈參數(shù)的角度:當(dāng)前坦克的角度+子彈應(yīng)該旋轉(zhuǎn)的角度Instantiate(bullectPrefab,transform.position,Quaternion.Euler(transform.eulerAngles+bullectEulerAugles));timeVal = 0;}}//坦克的移動(dòng)方法private void Move(){//監(jiān)聽玩家垂直軸輸入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];bullectEulerAugles = new Vector3(0, 0, -180);}else if (v > 0){sr.sprite = tankSprite[0];bullectEulerAugles = new Vector3(0, 0, 0);}if (v != 0){return;}//監(jiān)聽玩家水平軸輸入float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);if (h < 0){sr.sprite = tankSprite[3];bullectEulerAugles = new Vector3(0, 0, 90);}else if (h > 0){sr.sprite = tankSprite[1];bullectEulerAugles = new Vector3(0, 0, -90);}}//坦克的死亡方法private void Die(){if(isDefended){return;}PlayerManager.Instance.isDead = true;//產(chǎn)生爆炸特效 Instantiate(explosionPrefab, transform.position, transform.rotation);//死亡 Destroy(gameObject);} } Player.cs 游戲玩家
?
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement;public class PlayerManager : MonoBehaviour {//屬性值public int lifeVale = 3;public int playerScore = 0;public bool isDead=false;public bool isDefeat;//引用public GameObject born;//單例private static PlayerManager instance;public static PlayerManager Instance{get{return instance;}set{instance = value;}}public void Awake(){Instance = this;}// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {if(isDead){Recover();}}private void Recover(){if (lifeVale < 0){//游戲失敗,返回主界面 SceneManager.LoadScene("Game");}else{lifeVale--;GameObject go = Instantiate(born,new Vector3(-2,-8,0),Quaternion.identity);go.GetComponent<Born>().createPlay = true;isDead = false;}} } PlayerManager.cs 游戲玩家狀態(tài)管理?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class MapCreation : MonoBehaviour {//用來裝飾初始化地圖所需物體的數(shù)組//0.老家 1.墻 2.障礙 3.出生效果 4.河流 5.草 6.空氣墻public GameObject[] item;//已經(jīng)有東西位置的列表private List<Vector3> itemPositionList = new List<Vector3>();private void Awake(){//實(shí)例化老家CreateItem(item[0], new Vector3(0, -8, -0), Quaternion.identity);//用墻把老家圍起來CreateItem(item[1], new Vector3(-1, -8, -0), Quaternion.identity);CreateItem(item[1], new Vector3(1, -8, -0), Quaternion.identity);for(int i=-1;i<2;i++){Instantiate(item[1],new Vector3(i,-7,0),Quaternion.identity);}//坦克一開始就向下太難了,就直接給老家前面加了一頂墻CreateItem(item[2], new Vector3(0, -4, -0), Quaternion.identity);//實(shí)例化外圍墻for (int i=-11;i<12;i++){CreateItem(item[6], new Vector3(i, 9, 0), Quaternion.identity);}for(int i=-11;i<12;i++){CreateItem(item[6], new Vector3(i, -9, 0), Quaternion.identity);}for(int i=-8;i<9;i++){CreateItem(item[6], new Vector3(-11, i, 0), Quaternion.identity);}for(int i=-8;i<9;i++){CreateItem(item[6], new Vector3(11, i, 0), Quaternion.identity);}//初始化玩家GameObject go = Instantiate(item[3], new Vector3(-2, -8, 0), Quaternion.identity);go.GetComponent<Born>().createPlay = true;//產(chǎn)生敵人CreateItem(item[3], new Vector3(-10,8,0),Quaternion.identity);CreateItem(item[3], new Vector3(0, 8, 0), Quaternion.identity);CreateItem(item[3], new Vector3(10, 8, 0), Quaternion.identity);//第一次調(diào)用CreateEnemy用4s,每隔5s開調(diào)用InvokeRepeating("CreateEnemy",4,5);//實(shí)例化地圖for (int i=0;i<60;i++){CreateItem(item[1], CreateRamdomPosition(), Quaternion.identity);}for(int i=0;i<20;i++){CreateItem(item[2], CreateRamdomPosition(), Quaternion.identity);}for (int i = 0; i < 20; i++){CreateItem(item[4], CreateRamdomPosition(), Quaternion.identity);}for (int i = 0; i < 20; i++){CreateItem(item[5], CreateRamdomPosition(), Quaternion.identity);}}private void CreateItem(GameObject createGameObject,Vector3 createPosition,Quaternion createRotate){GameObject itemGo = Instantiate(createGameObject, createPosition, createRotate);itemGo.transform.SetParent(gameObject.transform);itemPositionList.Add(createPosition);}//產(chǎn)生隨機(jī)位置的方法private Vector3 CreateRamdomPosition(){//不生成x=-10,10的兩列,y=-8和8這兩行的位置while(true){Vector3 createPosition = new Vector3(Random.Range(-9, 10), Random.Range(-7, 8),0);if(!HasThePosition(createPosition)){return createPosition;}}}//用來判斷位置列表中是否有這個(gè)位置private bool HasThePosition(Vector3 createPos){for(int i=0;i<itemPositionList.Count;i++){if(createPos==itemPositionList[i]){return true;}}return false;}//產(chǎn)生敵人的方法private void CreateEnemy(){int num = Random.Range(0, 3);Vector3 EnemyPos = new Vector3();if(num==0){EnemyPos = new Vector3(-10, 8, 0);}else if(num==1){EnemyPos = new Vector3(0, 8, 0);}else{EnemyPos = new Vector3(10, 8, 0);}CreateItem(item[3],EnemyPos,Quaternion.identity);}} MapCreation.cs 初始化地圖?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Born : MonoBehaviour {public GameObject playerPrefab;public GameObject[] enemyPrefabList;//判斷是否產(chǎn)生敵人public bool createPlay;// Use this for initializationvoid Start () {Invoke("BornTank",1f);Destroy(gameObject,1f);}private void Update(){}private void BornTank(){if (createPlay){Instantiate(playerPrefab, transform.position, Quaternion.identity);}else{int num = Random.Range(0, 2);Instantiate(enemyPrefabList[num], transform.position, Quaternion.identity);}} } Born.cs 玩家敵人坦克出生?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Enemy : MonoBehaviour {//屬性值public float moveSpeed = 3;private Vector3 bullectEulerAugles;private float v=-1;private float h;//引用private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左public GameObject bullectPrefab;public GameObject explosionPrefab;//計(jì)時(shí)器public float timeVal;public float timeValChangeDirection=0;// Use this for initializationvoid Start(){sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update(){//攻擊的時(shí)間間隔if (timeVal >= 0.3f){//間隔大于0.4的時(shí)候才有攻擊效果 Attack();}else{timeVal += Time.deltaTime;}}private void FixedUpdate(){Move();}//坦克的攻擊方法private void Attack(){//子彈參數(shù)的角度:當(dāng)前坦克的角度+子彈應(yīng)該旋轉(zhuǎn)的角度Instantiate(bullectPrefab, transform.position, Quaternion.Euler(transform.eulerAngles + bullectEulerAugles));timeVal = 0;}//坦克的移動(dòng)方法private void Move(){if(timeValChangeDirection>=4){int num = Random.Range(0,8);if(num>5){v = -1;h = 0;}else if (num == 0){v = 1;h = 0;}else if (num > 0 && num <= 2){h = -1;v = 0;}else if (num > 2 && num <= 4){h = 1;v = 0;}timeValChangeDirection = 0;}else{timeValChangeDirection += Time.fixedDeltaTime;}//監(jiān)聽玩家垂直軸輸入 transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];bullectEulerAugles = new Vector3(0, 0, -180);}else if (v > 0){sr.sprite = tankSprite[0];bullectEulerAugles = new Vector3(0, 0, 0);}if (v != 0){return;}//監(jiān)聽玩家水平軸輸入 transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);if (h < 0){sr.sprite = tankSprite[3];bullectEulerAugles = new Vector3(0, 0, 90);}else if (h > 0){sr.sprite = tankSprite[1];bullectEulerAugles = new Vector3(0, 0, -90);}}//坦克的死亡方法private void Die(){PlayerManager.Instance.playerScore++;//產(chǎn)生爆炸特效 Instantiate(explosionPrefab, transform.position, transform.rotation);//死亡 Destroy(gameObject);}//優(yōu)化敵人AIprivate void OnCollisionEnter2D(Collision2D collision){if(collision.gameObject.tag=="Enemy"){timeValChangeDirection = 4;}}} Enemy.cs 敵人坦克?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Explosion : MonoBehaviour {// Use this for initializationvoid Start () {//坦克銷毀后0.167秒銷毀爆炸特效Destroy(gameObject,0.167f);}// Update is called once per framevoid Update () {} } Explosion.cs 游戲銷毀特效?
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Heart : MonoBehaviour {private SpriteRenderer sr;public GameObject explosionPrefab;public Sprite BrokenSprite; // Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}private void Die(){sr.sprite = BrokenSprite;Instantiate(explosionPrefab,transform.position,transform.rotation);PlayerManager.Instance.isDefeat = true;} } Heart.cs 心臟?
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement;public class Bullect : MonoBehaviour {public float moveSpeed = 10;public bool isPlayerBullect;// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {transform.Translate(transform.up*moveSpeed*Time.deltaTime,Space.World);}//子彈觸發(fā)碰撞檢測private void OnTriggerEnter2D(Collider2D collision){switch(collision.tag){case "Tank":if(!isPlayerBullect){collision.SendMessage("Die");Destroy(gameObject);}break;case "Heart":collision.SendMessage("Die");Destroy(gameObject);SceneManager.LoadScene("Game");break;case "Enemy":if(isPlayerBullect){collision.SendMessage("Die");Destroy(gameObject);}break;case "Wall"://銷毀自身和墻 Destroy(collision.gameObject);Destroy(gameObject);break;case "Barrier":Destroy(gameObject);break;default:break;}}} Bullect.cs 子彈?
轉(zhuǎn)載于:https://www.cnblogs.com/1138720556Gary/p/9795316.html
總結(jié)
以上是生活随笔為你收集整理的Unity3D_(游戏)2D坦克大战 像素版的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hbase 的javaAPI基本操作用
- 下一篇: Codeforces 1070A Fin