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