项目需求:
主⻆移动、坦克转身、开炮 敌⼈⼯⼚ ⽣成敌⼈大概就是这些功能啦!
博主只贴出脚本的实现,模型上的操作省略不表。
主角坦克类博主简单的设计了坦克的移动、状态、以及开炮动作
脚本代码如下:
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的!
点个关注,给个赞呗!