一起来玩U3D之坦克大战(单机)

Doris ·
更新时间:2024-11-13
· 883 次阅读

The War Of Tanks!!!

项目需求:

主⻆移动、坦克转身、开炮 敌⼈⼯⼚ ⽣成敌⼈
必须在空地⽣成
随机位置 、每隔3s⽣成⼀辆坦克 、设置敌⼈数量<=50辆 摄像机跟随 炮弹 敌⼈AI:随机转身、随机移动、开炮智能 距离判断 道具管理器:随机⽣成道具
每隔5秒⽣成⼀个道具 道具:禁锢敌⼈3s 50%、摧毁所有敌⼈ 5%、⽆敌5s 40%、召唤有个友⽅坦克 5%

大概就是这些功能啦!

博主只贴出脚本的实现,模型上的操作省略不表。

主角坦克类

博主简单的设计了坦克的移动、状态、以及开炮动作
脚本代码如下:

using UnityEngine; public class Tank : Unit { [Header("坦克移动速度")] public float moveSpeed; [Header("坦克转向速度")] public float turnSpeed; //获取坦克移动轴 private float hor; private float ver; //坦克的武器组件 private TankWeapon tankWeapon; [HideInInspector] //用于判断是否处于无敌状态 public bool isInvincible = false; private float invincibleTime = 5f; private float invincibleTimeCD = 0f; void Start () { tankWeapon = GetComponent(); } void Update () { //判断坦克是否无敌 if (isInvincible) { invincibleTimeCD += Time.deltaTime; if (invincibleTimeCD > invincibleTime) { isInvincible = false; invincibleTimeCD = 0f; } } //以下都是按键响应相应操作 if (Input.GetMouseButtonDown(0)) { tankWeapon.Shoot(); } hor = Input.GetAxis("HorizontalUI"); ver = Input.GetAxis("VerticalUI"); //控制前后移动 transform.Translate(Vector3.forward * ver * moveSpeed * Time.deltaTime); //控制左右转向 transform.Rotate(Vector3.up * hor * turnSpeed * Time.deltaTime); } //调用此方法可以使坦克无敌5秒 public void Invincible() { isInvincible = true; invincibleTimeCD = 0f; } } 坦克武器类

这个脚本中实现了坦克武器的基本操作

代码如下:

using UnityEngine; public class TankWeapon : MonoBehaviour { [Header("炮弹对象")] public GameObject shell; [Header("炮弹发射点")] public Transform shootPoint; [Header("发射力量")] public float shootPower; //声音组件 private AudioSource audioSource; void Start() { audioSource = GetComponent(); } /// /// 射击方法 /// public void Shoot() { //调用此方法时生成一个炮弹 GameObject newShell = Instantiate(shell, shootPoint.position, shootPoint.rotation); //获取炮弹的刚体组件 Rigidbody shellRigidbody = newShell.GetComponent(); //给炮弹一个初速度 shellRigidbody.velocity = shootPoint.forward * shootPower; //播放发射的声音 audioSource.Play(); } } 摄像机跟随主角坦克

这里我用的是最简陋的方式

代码如下:

using UnityEngine; public class TankCamera : MonoBehaviour { //一个空对象挂载着主角 public Transform target; void LateUpdate() { if (target == null) { return; } //这个空对象中有一个摄像机的子对象,让这个空对象跟着坦克走 transform.position = target.position; } } 炮弹实际效果类

细心的读者可能已经发现,博主在之前的武器类中和主角类中虽然写了发射炮弹,但是好像这个炮弹不会爆炸,也不会造成伤害。没错,这个脚本就是完成这件工作的。

代码如下:

using UnityEngine; public class ShellExplosion : MonoBehaviour { [Header("爆炸特效")] public GameObject shellExplosionPrefab; [Header("爆炸特效最大存留时间")] public float explosionTime; [Header("爆炸冲击力")] public float explosionForce; [Header("爆炸半径")] public float explosionRadius; [Header("爆炸伤害")] public int damage; void OnCollisionEnter() { //实例化爆炸效果且在最大留存时间到时销毁 Destroy(Instantiate(shellExplosionPrefab, transform.position, transform.rotation), explosionTime); //爆炸后销毁炮弹对象 Destroy(gameObject); //获取所有受到爆炸影响的碰撞体 Collider[] cols = Physics.OverlapSphere(transform.position, explosionRadius); //判断抓取的碰撞体集合是否为空 if (cols.Length>0) { //遍历所有碰撞体 for (int i = 0; i < cols.Length; i++) { //获取碰撞体所属对象的刚体 Rigidbody rig = cols[i].GetComponent(); if (rig != null) { //给对象刚体添加爆炸力 rig.AddExplosionForce(explosionForce, transform.position, explosionRadius); } //获取碰撞体所属对象的血条 Unit tankHP = cols[i].GetComponent(); //如果这个对象不为空且是处于无敌状态则不受伤害 if (tankHP != null && tankHP.tag.Equals("Player") && tankHP.GetComponent().isInvincible) { tankHP.UnderAttack(0); return; } if (tankHP != null) { //调用遭受攻击方法 tankHP.UnderAttack(damage); } } } } } 血条等(以后可能会加别的功能)类

代码如下:

using UnityEngine; public class Unit : MonoBehaviour { [Header("血量")] public int health = 100; //死亡后特效 public GameObject deadEffect; public void UnderAttack(int damage) { if (health > damage) { health -= damage; } else { //五秒后销毁坦克残骸 Destroy(Instantiate(deadEffect, transform.position, transform.rotation), 5f); Destruct(); } } void Destruct() { Destroy(gameObject); } } AI坦克(敌方)

这个就是重中之重了,不能写完了之后没有人跟我们对抗,那就没意思了,也不能这个敌方NPC太弱智,那也没意思,所以我们要写一个:人工智能(障)!

代码如下:

using UnityEngine; using UnityEngine.AI; public class AITank : Unit { [Header("开火的距离")] public float distance; [Header("移动速度")] public float moveSpeed; [Header("转向速度")] public float turnSpeed; [Header("射击冷却")] public float CDTime; //武器组件 private TankWeapon tankWeapon; //自动寻路组件 private NavMeshAgent navMeshAgent; private float time = 0f; private Vector3 randomPosition; private float randomTurnTime = 5f; //用以检测玩家 private GameObject player; //用于判断是否处于冻结状态 bool isFrozen = false; private float frezonTime = 3f; private float frezonTimeUp = 0f; void Start() { tankWeapon = GetComponent(); navMeshAgent = GetComponent(); randomPosition = new Vector3(Random.Range(-50f, 50f), 0.05f, Random.Range(-50f, 50f)); player = GameObject.FindWithTag("Player"); } //void FixedUpdate () { // time += Time.fixedDeltaTime; // if (player == null) // { // return; // } // float dis = Vector3.Distance(player.transform.position, transform.position); // if (dis > distance) // { // transform.Translate(Vector3.forward * Time.deltaTime * moveSpeed); // } // else // { // transform.LookAt(player.transform.position); // if (time > CDTime) // { // tankWeapon.Shoot(); // time = 0f; // } // } //} void Update() { //判断是否处于冻结状态 if (isFrozen) { navMeshAgent.ResetPath(); frezonTimeUp += Time.deltaTime; if (frezonTimeUp > frezonTime) { isFrozen = false; frezonTimeUp = 0f; } return; } //计算开火CD time += Time.deltaTime; if (player == null) { return; } //计算与玩家的距离 float dis = Vector3.Distance(player.transform.position, transform.position); //与玩家距离过远则执行以下代码 if (dis > distance) { //计算随机转向的时间 randomTurnTime -= Time.deltaTime; //如果随机转向时间满足,就转向 if (randomTurnTime <= 0) { randomTurnTime = 5f; randomPosition = new Vector3(Random.Range(-50f, 50f), 0.05f, Random.Range(-50f, 50f)); } if (Vector3.Distance(randomPosition,transform.position) CDTime) { tankWeapon.Shoot(); time = 0f; } } } } } //调用此方法将是AI冻结3秒 public void Frezon() { isFrozen = true; frezonTimeUp = 0f; } } 坦克工厂

有了AI坦克,我们需要随机生成AI
代码如下:

using UnityEngine; public class TanksFactory : MonoBehaviour { [Header("想要在地图上随机生成的对象")] public GameObject randomProductObj; [Header("生成时的障碍检测半径")] public float testRadius; [Header("生成对象间隔")] public float prodcutCD; //计时器 private float productTime; //设置随机生成地点 private Vector3 randomProductPosision; void Start() { productTime = prodcutCD; } void Update() { //计算生成冷却时间 productTime -= Time.deltaTime; if (productTime > 0) { return; } //获取一个随机位置 randomProductPosision = new Vector3(Random.Range(-45f, 45f), testRadius + 0.1f, Random.Range(-45f, 45f)); //检测获取的位置是否是空地 Collider[] cols = Physics.OverlapSphere(randomProductPosision, testRadius); //若是空地,生成一辆AI坦克 if (cols.Length < 1) { Instantiate(randomProductObj, randomProductPosision, Quaternion.identity); productTime = prodcutCD; } } } AI队友

那么道具中有一个是生成一个队友,我们就做个人工智能队友,因为跟AITANK差不多,我就简写了一点

代码如下:

using UnityEngine; using UnityEngine.AI; public class AIFriend : Unit { [Header("射击冷却时间")] public float shootCD; [Header("转身速度")] public float turnSpeed; //用以获取敌人位置 private GameObject enemy; private TankWeapon tankWeapon; //自动寻路 NavMeshAgent agent; float shootTimeCD = 0f; void Start() { //每隔五秒重新获取一个敌人位置 InvokeRepeating("GetTarget", 0.5f, 5f); tankWeapon = GetComponent(); agent = GetComponent(); } void Update() { shootTimeCD += Time.deltaTime; if (enemy == null) { return; } //自动寻路到敌人 agent.SetDestination(enemy.transform.position); Vector3 dir = enemy.transform.position - transform.position; Quaternion rotate = Quaternion.LookRotation(dir); transform.rotation = Quaternion.Lerp(transform.rotation, rotate,turnSpeed * Time.deltaTime); //射线碰撞检测 Ray ray = new Ray(transform.position + transform.up, transform.forward); RaycastHit hitInfo; if (Physics.Raycast(ray,out hitInfo)) { GameObject obj = hitInfo.collider.gameObject; if (obj != null && obj.tag.Equals("enemy")) { if (shootTimeCD > shootCD) { tankWeapon.Shoot(); shootTimeCD = 0f; } } } } void GetTarget() { enemy = GameObject.FindWithTag("enemy"); } } 道具之冻结敌人3秒

代码如下:

using UnityEngine; public class FrozenEnemy : MonoBehaviour { void OnTriggerEnter(Collider player) { //如果玩家触发此触发器,冻结所有敌人3秒并销毁此触发器 if (player.tag.Equals("Player")) { GameObject[] enemys = GameObject.FindGameObjectsWithTag("enemy"); if (enemys.Length > 0) { foreach (var item in enemys) { item.GetComponent().Frezon(); } } Destroy(gameObject); } else { return; } } } 道具之无敌

代码如下:

using UnityEngine; public class Invincible : MonoBehaviour { void OnTriggerEnter(Collider player) { //如果玩家触发此触发器,玩家将获得无敌状态5秒 if (player.tag.Equals("Player")) { player.GetComponent().Invincible(); Destroy(gameObject); } else { return; } } } 道具之召唤友军

代码如下:

using UnityEngine; public class CallSupport : MonoBehaviour { [Header("友方AI坦克对象")] public GameObject friendTankPrefab; void OnTriggerEnter(Collider player) { //当玩家触发此触发器,将召唤一个友军坦克加入战斗 if (player.tag.Equals("Player")) { Instantiate(friendTankPrefab, transform.forward, transform.rotation); Destroy(gameObject); } else { return; } } } 道具之摧毁全部敌方坦克

代码如下:

using UnityEngine; public class KillAllEnemy : MonoBehaviour { void OnTriggerEnter(Collider player) { //若玩家触发此触发器,将清除场景中所有的敌方坦克 if (player.tag.Equals("Player")) { GameObject[] enemys = GameObject.FindGameObjectsWithTag("enemy"); if (enemys.Length > 0) { foreach (var item in enemys) { Destroy(item); } } Destroy(gameObject); } else { return; } } } 道具生成器

代码如下:

using UnityEngine; public class PropFactory : MonoBehaviour { [Header("冻结敌人的道具")] public GameObject frezon; [Header("清除所有敌人的道具")] public GameObject killAllEnemy; [Header("无敌5秒的道具")] public GameObject invincible; [Header("召唤支援的道具")] public GameObject callSupport; [Header("生成时的障碍检测半径")] public float testRadius; [Header("生成对象间隔")] public float prodcutCD; //计时器 private float productTime; //设置随机生成地点 private Vector3 randomProductPosision; void Start() { productTime = prodcutCD; } void Update() { //计算CD productTime -= Time.deltaTime; if (productTime > 0) { return; } //获取随机位置 randomProductPosision = new Vector3(Random.Range(-45f, 45f), testRadius + 0.1f, Random.Range(-45f, 45f)); //判断该位置是不是空地 Collider[] cols = Physics.OverlapSphere(randomProductPosision, testRadius); //若是空地则按照概率随机生成上面四个道具中的一个 if (cols.Length < 1) { //获取0-100的一个随机数模拟一个概率 float probability = Random.Range(0f, 100f); if (probability < 5f) { Instantiate(killAllEnemy, randomProductPosision, Quaternion.identity); productTime = prodcutCD; } else if(probability < 10f) { Instantiate(callSupport, randomProductPosision, Quaternion.identity); productTime = prodcutCD; } else if (probability < 50f) { Instantiate(invincible, randomProductPosision, Quaternion.identity); productTime = prodcutCD; } else { Instantiate(frezon, randomProductPosision, Quaternion.identity); productTime = prodcutCD; } } } } 好啦,那我们的The War Of Tanks!!!的1.0版本就做好了,有时间我会更新2.0的!

点个关注,给个赞呗!


作者:第五枫咏



坦克大战 u3d

需要 登录 后方可回复, 如果你还没有账号请 注册新账号