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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/366895.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

认识Skeleton Screen【屏幕加载骨架】

一直以来&#xff0c;无论是web还是iOS、android的应用中&#xff0c;为了提升应用的加载等待这段时间的用户感知体验&#xff0c;各种奇门遁甲之术层出不穷。其中&#xff0c;菊花图以及由它衍生各种加载动画是一个非常大的流派&#xff0c;如下图所示&#xff1a;由它衍生而出…

一日三项令人兴奋的Lucene功能

昨天是富有成效的一天&#xff1a;突然&#xff0c;Lucene有了三个令人兴奋的新功能。 表达式模块 昨天提交的第一个功能是新的expressions模块 。 这使您可以使用任意String表达式定义用于排序的动态字段。 内置了对JavaScript解析的支持&#xff0c;但是如果您想创建自己的语…

php date当天,php5中date()获得的时间不是当前时间的解决方法

自php5.10起加入了时区的设置&#xff0c;在php中显示的时间都是格林威治标准时间&#xff0c;因此便与中国的用户会差八个小时。修改php.ini中的 date.timezone 参数&#xff1a;复制代码 代码如下:[Date]; Defines the default timezone used by the date functions;date.tim…

listening for variable changes in javascript

https://stackoverflow.com/questions/1759987/listening-for-variable-changes-in-javascript转载于:https://www.cnblogs.com/wangjixianyun/p/9115336.html

JPA EntityListeners中的Spring注入的Bean

在使用JPA侦听器进行数据库加密中&#xff0c;我讨论了使用JPA EntityListener进行透明加密。 从某种意义上说&#xff0c;这种方法是透明的&#xff0c;因为JPA实体&#xff08;几乎&#xff09;完全不知道正在加密&#xff0c;而JPA EntityListener本身也不知道细节。 有一个…

php sql 去除重复数据,MSSQL_快速删除重复记录,SQL Server如何实现?,如果一张表的数据达到上百万 - phpStudy...

如果一张表的数据达到上百万条&#xff0c;用游标的方法来删除简直是个噩梦&#xff0c;因为它会执行相当长的一段时间……开发人员的噩梦——删除重复记录想必每一位开发人员都有过类似的经历&#xff0c;在对数据库进行查询或统计的时候不时地会碰到由于表中存在重复的记录而…

Python运行的方式

Python的运行方式多种多样&#xff0c;下面列举几种: 交互式 在命令行中输入python&#xff0c;然后在>>>提示符后面输入Python语句&#xff0c;这里需要注意: 1 语句前面不能有空格&#xff0c;否则会报错 2 对于符合语句&#xff0c;前面会有...提示符&#xff0c;结…

使用Apache Zookeeper进行协调和服务发现

面向服务的设计已被证明是针对各种不同的分布式系统的成功解决方案。 如果使用得当&#xff0c;它会带来很多好处。 但是随着服务数量的增加&#xff0c;了解部署什么以及部署在何处变得更加困难。 而且&#xff0c;由于我们正在构建可靠且高度可用的系统&#xff0c;因此还需要…

微信小程序无埋点数据采集方案

作者&#xff1a;lxj&#xff0c;点餐终端团队成员前言 相信业务团队对这样的场景不会太陌生&#xff1a;打点需求&#xff1a; 每新上一个功能&#xff0c;数据产品便会同步加上打点需求&#xff0c;当数据打点上线后一段时间&#xff0c;数据产品/业务产品便会针对数据的转化…

php 状态码302,HTTP状态码302、303和307的故事

今日读书&#xff0c;无法理解HTTP302、303、307状态码的来龙去脉&#xff0c;决定对其做深究并总结于本文。《HTTP权威指南》第3章在讲解30X状态码时&#xff0c;完全没有讲清楚为什么要有302、303、307&#xff0c;以及他们的关系&#xff0c;一句“问题出在HTTP/1/1”让我一…

Codeforces 1070A Find a Number(BFS) 2018-2019 ICPC, NEERC, Southern Subregional Contest Problem A

Description You are given two positive integers ddd and sss. Find minimal positive integer nnn which is divisible by ddd and has sum of digits equal to sss.Input The first line contains two positive integers ddd and sss(1≤d≤500,1≤s≤5000)(1≤d≤500,1≤s…

luogu3807 【模板】 卢卡斯定理

题目大意 对于一个很大的$n,m,p$如何求$C_{nm}^m\mod p$&#xff1f; Lucas定理 若$n_i,m_i$分别是$n,m$在$p$进制下第$i$位的数字&#xff0c;则有 $$C_n^m\mod p\prod_{i0}^{\log_p m}C_{n_i}^{m_i}\mod p$$ 求法 按照定理式一个一个求组合数即可。 组合数并不用批量求。故预…

防止System.exit调用

在开发运行其他开发人员编写的代码的容器时&#xff0c;请谨慎防范System.exit调用。 如果开发人员无意间调用了System.exit并将其代码部署为由您的容器运行&#xff0c;则它将完全降低容器进程。 可以使用SecurityManager中的checkExit函数调用来控制。 根据SecurityManager …

php异步请求$.post,如何用PHP实现异步请求、忽略返回值

本篇文章的主要内容是用PHP实现异步请求、忽略返回值&#xff0c;具有一定的参考价值&#xff0c;有需要的朋友可以看看&#xff0c;希望能对你有帮助。项目需要&#xff0c;场景如下&#xff1a;某个条件下需要调用接口发送多个请求执行脚本&#xff0c;但是由于每个请求下的脚…

JavaScript函数式编程学习

本文是我在函数式编程学习过程中&#xff0c;总结的笔记&#xff0c;也分享给想学函数式编程的同学。 函数式编程可能对于初学者来说&#xff0c;概念难以理解&#xff0c;入门比较难。所以本文从两部分去学习。 在你身边你左右 --函数式编程别烦恼 第一部分&#xff0c;你身…

读书印记 - 《沟通的艺术:一本手把手教你社交沟通的书》

一个教训是没上过榜也没什么好推荐的书有挺大概率不是本好书。我现在不太能耐心的去读这种指导手册&#xff0c;一是谈话的技巧需要在实战中才能有效提升&#xff0c;二是这方面对我来说不是关注的重点。所以几乎是刷刷的翻完了整本书。当然也不能说这本书就是烂书&#xff0c;…

Linux NTP

ntpd服务的设置: ntpd服务的相关设置文件如下&#xff1a; /etc/ntp.conf&#xff1a;这个是NTP daemon的主要设文件&#xff0c;也是 NTP 唯一的设定文件。/usr /share/zoneinfo/:在这个目录下的文件其实是规定了各主要时区的时间设定文件&#xff0c;例如北京地区的时区设定文…

Java Web项目的保存和刷新

如何配置计算机以保存并刷新Java Web项目&#xff1f; 当您向开发人员提出此问题时&#xff0c;答案以“哦&#xff0c;好吧……”开头&#xff0c;并以某种可行的方式继续描述。 每个人都有自己的方式。 首先–为什么需要这个&#xff1f; 因为执行复制和重新启动服务器是生产…

mysql alter怎么用,mysql alter话语用法

mysql alter语句用法//主键ALTER TABLE tablename add new_field_id int(5) UNSIGNED DEFAULT 0 NOT NULL anto_increment,ADD PRIMARY KEY (new_field_id);//增加一个新列mysql>ALTER TABLE tablename ADD fieldname fieldtype如&#xff1a;ALTER TABLE t2 ADD d TIMESTAM…

《React 学习之道》The Road to learn React (简体中文版)

通往 React 实战大师之旅&#xff1a;掌握 React 最简单&#xff0c;且最实用的教程。 前言 《React 学习之道》这本书使用路线图中的精华部分用于传授 React&#xff0c;并将其融入一个独具吸引力的真实世界 App的具体代码实现。 如何掌握 React 存在特别多的路线图。本书提…