您的位置:首页 > 移动开发 > Unity3D

Unity实例-坦克大战

2016-03-14 20:07 375 查看
这个示例使用了官方教程的素材,自建脚本之后实现与原游戏的不同感觉。

1.这个坦克大战主要是实现了几组敌对坦克的互相混战(通过设置不同的层级来识别)。AI坦克有搜寻敌对坦克,自动寻路自动开火功能。

由本方的炮弹击中敌对的坦克会对对方产生力的效果并执行伤害计算。坦克死亡的时候会生成死亡坦克对象并播放爆炸效果;

1.玩家视角控制脚本

using UnityEngine;
using System.Collections;

public class FYLcamera : MonoBehaviour {

public Transform target;//被观测物体
public Transform childCamera;//摄像机
public float rotateSpeed;//旋转速度
public float scaleSpeed;//缩放速度
public float minDistance;//最近缩放位置
public float maxDistance;//最远缩放位置

private float currentScale;//现有的缩放大小
private Vector3 currentRotation;//现有的旋转角
private Vector3 lastMousePosition;//记录鼠标上次的位置
// Use this for initialization
void Start () {
currentScale = childCamera.position.z;//初始化缩放大小
currentRotation = transform.eulerAngles;//初始化欧拉角
lastMousePosition = Input.mousePosition;
}

// Update is called once per frame
void LateUpdate () {
if (target == null)
return;
Vector3 mouseDelta = Input.mousePosition - lastMousePosition;//计算鼠标位移
lastMousePosition = Input.mousePosition;

if (Input.GetMouseButton (1)) {//如果使用鼠标右键

currentRotation.x += mouseDelta.y * rotateSpeed * Time.deltaTime;
currentRotation.y += mouseDelta.x * rotateSpeed * Time.deltaTime;
//因为旋转方向和鼠标拖动方向正好相反,所以用以上公式计算旋转量
}
currentScale += -Input.mouseScrollDelta.y * scaleSpeed * Time.deltaTime;//计算缩放值,因为我的摄像机是反的,所以要取负数
currentScale = Mathf.Clamp (currentScale, minDistance, maxDistance);//取闭区间,使得缩放值一直在规定的范围之内
transform.position = target.position;//空物体的坐标跟随被观测物体
transform.eulerAngles = currentRotation;//欧拉角设定为当前的旋转量
childCamera.localPosition = new Vector3 (0, 0, currentScale);//设定摄像机的缩放距离。
}
}


2.玩家行动开火控制脚本

using UnityEngine;
using System.Collections;

public class playercontroller : Unit {

public float moveSpeed;//移动速度
public float rotateSpeed;//旋转速度

e16b
public int MaxHealth=200;//最大生命值,用于画血条

private Tankweapon tk;

public int getMaxHealth()
{
return MaxHealth;
}
void Start()
{
tk = GetComponent<Tankweapon> ();
tk.Init(team);
}
void FixedUpdate ()
{
float horizontal = Input.GetAxis ("Horizontal1");
float vertical = Input.GetAxis ("Vertical1");

transform.Translate (Vector3.forward * moveSpeed * Time.deltaTime * vertical);
transform.Rotate (Vector3.up * rotateSpeed * Time.deltaTime * horizontal);//移动函数
if (Input.GetKey (KeyCode.Space)) {
tk.shoot ();

}

}
}


3.通用的武器控制脚本

using UnityEngine;
using System.Collections;

public class Tankweapon : MonoBehaviour {

public GameObject shall;//炮弹对象
public float shootpower;//设计力量
public Transform shootPoint;//炮弹生成点
public float shootwait;//发射延时

private LayerMask enemyLayer; //敌人的层

private bool isWeaponReady=true;
public void Init(Team team)
{
enemyLayer = layerManger.getEnemyLayer (team);
}

public void shoot()
{
if (!isWeaponReady)
return;
GameObject newshall=Instantiate (shall, shootPoint.position,shootPoint.rotation) as GameObject;//生成炮弹
//if (!newshall.GetComponent<allShall> ().isenemyShall)
newshall.GetComponent<Shall> ().Init (enemyLayer);//设定炮弹要攻击的坦克的层级,属于这些层的才会造成伤害
//else
//newshall.GetComponent<Enemyshall> ().Init (enemyLayer);
Rigidbody r = newshall.GetComponent<Rigidbody> ();
r.velocity = shootPoint.forward * shootpower;//设定速度
GetComponent<AudioSource> ().Play ();//播放音效
isWeaponReady = false;
StartCoroutine (weaponColdDown ());//冷却武器的协程

}

IEnumerator weaponColdDown()
{

yield return new WaitForSeconds (shootwait);
isWeaponReady = true;//用于控制武器冷却时间的协程
}
}


4.坦克通用对象脚本(玩家与AI坦克的共同属性)

using UnityEngine;
using System.Collections;
public enum Team
{
Blue,Red,Green,Black,Gold
}//划分队伍
public class Unit : MonoBehaviour {
public Team team;
public int health;

public GameObject deadEffct;//死亡效果

public void applyDamage(int Damage)
{
if (health > Damage) {
health -= Damage;
} else {
health = 0;
Destruct ();//生命值扣完执行毁灭函数
}
}
public void Destruct()
{
if (deadEffct != null) {
Instantiate (deadEffct, transform.position, transform.rotation);//生成死亡坦克对象
}
Destroy (gameObject);//销毁当前对象

}
}


5.炮弹的脚本

using UnityEngine;
using System.Collections;

public class Shall :  MonoBehaviour {
public GameObject explosionEffect;//爆炸效果的预设对象
public float explosionRadius;//爆炸半径
public float explosionforce;//爆照的力量
public int Damage;//每一击的伤害

private LayerMask curLayer;//当前敌人的层
public void Init(LayerMask enemyLayer)
{
curLayer = enemyLayer;//获得敌人的层

}
void OnCollisionEnter()//碰撞检测
{

Instantiate (explosionEffect, transform.position, transform.rotation);//生成爆炸效果
Destroy (gameObject);//销毁炮弹
Collider[] colliders=Physics.OverlapSphere (transform.position, explosionRadius,curLayer);//检测爆炸范围内的敌人
if (colliders.Length > 0) {

for (int i = 0; i < colliders.Length; i++) {

Rigidbody rb = colliders [i].GetComponent<Rigidbody> ();
if (rb != null)
rb.AddExplosionForce (explosionforce, transform.position, explosionRadius);//对物体加一个力

Unit un = colliders [i].GetComponent<Unit> ();
if (un != null) {

un.applyDamage (Damage);//造成伤害

}
}

}

}
}


6.层级控制的脚本

using UnityEngine;
using System.Collections;

public class layerManger : MonoBehaviour {

static public int blueLayer=10;
static public int redLayer=11;
static public int greenLayer=12;
static public int blackLayer=13;
static public int goldLayer=14;//以上都是每个层对应的数字,在unity编辑器里可以设置

static public LayerMask getEnemyLayer(Team team)
{
LayerMask mask=0;
switch(team)//给游戏对象赋予他们敌对势力的层,层是由32位来表示的,在哪一位上为1,说明这个层就被激活。比如层1就是0000.。。0001,而或操作可以整合有效的层
{
case Team.Blue:
mask = (1 <<redLayer) | (1 <<greenLayer) | (1 <<blackLayer) | (1 <<goldLayer);
break;
case Team.Red:
mask = (1 <<blueLayer) | (1 <<greenLayer) | (1 <<blackLayer) | (1 <<goldLayer);
break;
case Team.Black:
mask = (1 <<redLayer) | (1 << greenLayer) | (1 << blueLayer) | (1 << goldLayer);
break;
case Team.Gold:
mask = (1 << redLayer) | (1 << greenLayer) | (1 << blackLayer) | (1 << blueLayer);
break;
case Team.Green:
mask = (1 << redLayer) | (1 << blueLayer) | (1 << blackLayer) | (1 << blueLayer);
break;
}

return mask;
}

}


7.AI坦克的脚本

using UnityEngine;
using System.Collections;

public class AItank : Unit {
public float moveSpeed;//移动速度
public float rotateSpeed;//旋转速度
//public LXRange attackRange;
public LXRange stoppingDistance;//停止距离,相当于对方的AT力场,绝对无法进入,值类型是我自定义的
public float enemySearchRange;//敌人坦克的搜索雷达范围
public float aiCoreTimerInterval;//敌人计算对方的AT力场范围的冷却时间

public GameObject enemy;//需要攻击的坦克对象
private Tankweapon tk;//武器组件
private NavMeshAgent nma;//自动寻路代理组件的变量
private LayerMask enemyLayer;//保存一组层的数据
//private float curAR;
private float curSD;//当前停止距离
// Use this for initialization
IEnumerator Timer()//计算停止距离的协程
{
while (enabled) {//相当于whlie(true),enabled指的是碰撞器
//curAR = LXMath.Random (attackRange);
curSD = LXMath.Random (stoppingDistance);//返回最大值与最小值之间的一个随机数
yield return new WaitForSeconds (aiCoreTimerInterval);//挂起几秒
}

}

void searchEnemy()
{

Collider[] cor = Physics.OverlapSphere (transform.position, enemySearchRange, enemyLayer);//当前在搜索范围内,且属于指定层级的碰撞体
/*Vector3 mindist = Mathf.Abs (transform.position - cor [0].transform.position);//这个是为了找出最近敌人
Vector3 temp;
int minIdex = 0;
for (int j = 1; j < cor.Length; j++) {
temp = transform.position - cor [j].transform.position;
if (temp < mindist) {
mindist = temp;
mindist=j
}
}*/

int i = Random.Range (0, cor.Length);//随机确定一个搜索范围内的敌人的下标
if (cor[i]) {//如果这个敌人存在
enemy = cor [i].gameObject;//把敌人设为攻击目标
}
}

void Start () {
enemyLayer = layerManger.getEnemyLayer (team);//获得所有敌人的层级
nma = GetComponent<NavMeshAgent> ();//获得寻路代理组件
tk = GetComponent<Tankweapon> ();//获得武器组件
tk.Init (team);//武器的init函数,给武器指定要攻击的对象
StartCoroutine (Timer ());
}

// Update is called once per frame
void FixedUpdate () {
if (enemy == null) {
searchEnemy ();
return;
}//当没有攻击目标时,自动搜索
Vector3 dir = enemy.transform.position - transform.position;//计算和敌人的相对距离,三维距离
Quaternion wantedRotation = Quaternion.LookRotation (dir);//计算物体朝向的敌人的方向
float dist = Vector3.Distance (enemy.transform.position, transform.position);//和敌人的距离,直线距离

if (dist > curSD) {
transform.rotation = Quaternion.Slerp (transform.rotation, wantedRotation, rotateSpeed * Time.deltaTime);
nma.SetDestination(enemy.transform.position);//向敌人前进,并始终转向敌人

}

float shootRange = curSD + 2f;//射击距离
if (dist < shootRange) {
nma.ResetPath ();//重新计算到敌人位置的网点路径
transform.rotation = Quaternion.Slerp (transform.rotation, wantedRotation, rotateSpeed * Time.deltaTime);
tk.shoot ();

}
//  StartCoroutine (AIshoot ());
}
/*  IEnumerator AIshoot()
{
yield return new WaitForSeconds (fireCooling);
tk.shoot ();
}*/
}


8.游戏控制脚本

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class GameController : MonoBehaviour {

public GameObject[] hazard;//对象数组
public Transform[] spawnPoint; //出生地点数组
public float timer;//生成延时
public Text restart;
public Text healthLabel;
public Image healthBar;
public Text GameOver;//以上几个就是UI对象
public playercontroller player;//玩家对象

IEnumerator creatEnemy()
{
while (true) {
for (int i = 0; i < hazard.Length; i++) {

Instantiate (hazard [i], spawnPoint [i].position, spawnPoint[i].rotation);

}
yield return new WaitForSeconds (timer);//这个函数用于延时生成新坦克
}

}
void Start () {
GameOver.text="";
restart.text = "";
StartCoroutine (creatEnemy ());

}

void Update () {
if (player.health == 0) {
GameOver.text = "游戏结束";
restart.text = "按R重新开始";
}
healthBar.fillAmount = (float)player.health/player.getMaxHealth();//按比例控制血条填充的角度,取值是(0,1),1对应36
healthLabel.text = player.health.ToString ();
if (Input.GetKeyDown (KeyCode.R)) {

Application.LoadLevel (Application.loadedLevel);//重新加载现有场景
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: