Unity3D_(游戏)2D坦克大战 像素版

   游戏基础界面搭建完成,和玩家互动UI与10月25日前完成~

  当玩家被击杀次数>=3  或  心脏被子弹击穿  重新加载游戏场景

 

  游戏完成时放上源码~ 

场景搭建

  设置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 initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        //监听玩家水平轴输入
        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);
    }
}
Player.cs

控制图片的移动和切换

  制作坦克渲染

  添加精灵数组的引用

    private SpriteRenderer sr;
    public Sprite[] tankSprite;

(上 右 下 左)

  玩家按上下左右控制坦克方向的移动

//监听玩家水平轴输入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.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 initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }
    
    // Update is called once per frame
    void Update () {
        //监听玩家水平轴输入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.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 1
        transform.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 initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }
    
    // Update is called once per frame
    void Update () {
        //监听玩家水平轴输入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.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 1
        transform.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 initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }
    
    // Update is called once per frame
    void 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 1
        transform.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 initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }
    
    // Update is called once per frame
    void 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 1
        transform.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 initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        //监听玩家水平轴输入
        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);
    }
}
Player.cs

控制图片的移动和切换

  制作坦克渲染

  添加精灵数组的引用

    private SpriteRenderer sr;
    public Sprite[] tankSprite;

(上 右 下 左)

  玩家按上下左右控制坦克方向的移动

//监听玩家水平轴输入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.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 initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }
    
    // Update is called once per frame
    void Update () {
        //监听玩家水平轴输入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.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 1
        transform.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 initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }
    
    // Update is called once per frame
    void Update () {
        //监听玩家水平轴输入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.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 1
        transform.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 initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }
    
    // Update is called once per frame
    void 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 1
        transform.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 initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }
    
    // Update is called once per frame
    void 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 1
        transform.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 initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }

  添加Heart.cs心脏死亡时方法

    private void Die()
    {
        sr.sprite = BrokenSprite; 
    }

  添加Explosion.cs脚本

  当坦克销毁时触发脚本

public class Explosion : MonoBehaviour {

    // Use this for initialization
    void Start () {
        //坦克销毁后0.167秒销毁爆炸特效
        Destroy(gameObject,0.167f);
    }
    
    // Update is called once per frame
    void 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 initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }
    
    // Update is called once per frame
    void Update () {
        //保护是否处于无敌状态
        if(isDefended)
        {
            defendEffectPrefab.SetActive(true);
            defendTimeVal -= Time.deltaTime;
            if (defendTimeVal<=0)
            {
                isDefended = false;
                defendEffectPrefab.SetActive(false);
            }
        }

        //攻击的CD
        if (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 1
        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()
    {
        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 initialization
    void Start () {
        //坦克销毁后0.167秒销毁爆炸特效
        Destroy(gameObject,0.167f);
    }
    
    // Update is called once per frame
    void 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 initialization
    void 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 initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void 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 initialization
    void Start()
    {
        sr = GetComponent<SpriteRenderer>();
    }

    // Update is called once per frame
    void Update()
    {
        //保护是否处于无敌状态
        if (isDefended)
        {
            defendEffectPrefab.SetActive(true);
            defendTimeVal -= Time.deltaTime;
            if (defendTimeVal <= 0)
            {
                isDefended = false;
                defendEffectPrefab.SetActive(false);
            }
        }

        //攻击的CD
        if (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 1
        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()
    {
        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 initialization
    void 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 initialization
    void Start () {
        Invoke("BornTank",0.8f);
        Destroy(gameObject,0.8f);
    }
    
    // Update is called once per frame
    void 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 initialization
    void 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 initialization
    void Start()
    {
        sr = GetComponent<SpriteRenderer>();
    }

    // Update is called once per frame
    void 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 initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void 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 initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void 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 initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }
    
    // Update is called once per frame
    void Update () {
        //保护是否处于无敌状态
        if(isDefended)
        {
            defendEffectPrefab.SetActive(true);
            defendTimeVal -= Time.deltaTime;
            if (defendTimeVal<=0)
            {
                isDefended = false;
                defendEffectPrefab.SetActive(false);
            }
        }

        //攻击的CD
        if (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 1
        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()
    {
        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 initialization
    void 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 initialization
    void Start()
    {
        sr = GetComponent<SpriteRenderer>();
    }

    // Update is called once per frame
    void 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);
    }

    //优化敌人AI
    private 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 initialization
    void Start () {
        //坦克销毁后0.167秒销毁爆炸特效
        Destroy(gameObject,0.167f);
    }
    
    // Update is called once per frame
    void 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 initialization
    void 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 initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void 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;

猜你喜欢

转载自www.cnblogs.com/1138720556Gary/p/9795316.html