大家好,我是秦元培,欢迎大家继续关注我的博客,我的博客地址是blog.csdn.net/qinyuanpei

首先感谢大家对我博客的关注,今天我想和大家分享的是一个飞机大战的项目。这是一个比較综合的项目,希望对大家学习Unity3D有所帮助,我会在文章最后给出项目代码。

作为一个游戏而言。游戏策划十分重要,所以在開始今天的文章之前,我们先来了解下这个项目的策划。

我们的玩家是一个飞机。玩家能够使用A、D、S、W四个键位来控制飞机位置,当按下空格键时,我方飞机能够向敌机发射炮弹。当敌机中弹后将降低生命值。当敌机生命值为0时,敌机将爆炸销毁。在游戏场景中仅仅有一种从屏幕上方不断向下飞行的敌机。当我方飞机与敌机碰撞后,两方都将降低生命值。当我方生命值降低至0时。游戏将结束。好了。了解完游戏规则设定后,我们就能够開始今天的内容了。

一、游戏场景

游戏场景我们採用2D的界面。如图。我们创建一个蓝天白云的平面场景。该场景垂直于摄像机并採取正交投影方式。假设对在Unity3D中创建2D场景尚存在疑惑的朋友能够參考文章《[Unity3D]Unity3D游戏开发之《经典打砖块》游戏的实现》《Unity3D游戏开发之使用Unity3D开发2D游戏 (一)》两篇文章。

我们这里在场景中加入GUIText对象来显示玩家得分等基本信息,脚本定义例如以下:

using UnityEngine;
using System.Collections; public class GameManager : MonoBehaviour { //玩家得分
private Transform Grade;
//玩家生命
private Transform HP;
//游戏结束
private Transform Text;
//玩家
private GameObject Player; void Start ()
{
//初始化界面
Grade=transform.Find("Grade");
HP=transform.Find("HP");
Text=transform.Find("Text");
Text.guiText.enabled=false;
//获取玩家对象
Player=GameObject.Find("Player");
} void Update ()
{
if(Player!=null)
{
//更新UI
Grade.guiText.text="得分:"+Player.GetComponent<Player>().Grade.ToString();
HP.guiText.text="生命:"+Player.GetComponent<Player>().MaxHP.ToString();
}
if(HP.guiText.text=="生命:0")
{
Text.guiText.enabled=true;
//马上复活
if(Input.GetKey(KeyCode.Y))
{
Application.LoadLevel("Main");
}
//退出
if(Input.GetKey(KeyCode.N))
{
Application.Quit();
}
}
}
}

二、玩家飞机

玩家飞机的创建和背景的创建时相同的,这里我们不再多说。

玩家飞机须要完毕移动、发射、碰撞的事件处理。为此我们编写以下的脚本:

using UnityEngine;
using System.Collections; public class Player : MonoBehaviour { //飞机的移动速度
public float MoveSpeed;
//飞机的最大生命值
public int MaxHP=100;
//定义子弹对象
public GameObject Bullet;
//定义子弹发射位置
private Transform BulletPosL;
private Transform BulletPosR; [HideInInspector]
public int Grade=0; void Start ()
{
BulletPosL=this.transform.Find("BulletPosL");
BulletPosR=this.transform.Find("BulletPosR");
} void Update ()
{
if(Input.GetKey(KeyCode.A))
{
transform.Translate(Vector3.left*Time.deltaTime*(-MoveSpeed));
}
if(Input.GetKey(KeyCode.D))
{
transform.Translate(Vector3.left*Time.deltaTime* MoveSpeed );
}
if(Input.GetKey(KeyCode.W))
{
transform.Translate(Vector3.forward*Time.deltaTime*(-MoveSpeed));
}
if(Input.GetKey(KeyCode.S))
{
transform.Translate(Vector3.forward*Time.deltaTime*MoveSpeed);
}
//按下空格键,发射子弹
if(Input.GetKey(KeyCode.Space))
{
Instantiate(Bullet,BulletPosL.transform.position,Quaternion.Euler(new Vector3(0,1,0)));
Instantiate(Bullet,BulletPosR.transform.position,Quaternion.identity);
}
} #region 减血
public void Hit(int Value)
{
if(MaxHP>0)
{
MaxHP-=Value;
}else
{
Destroy(this.gameObject);
}
}
#endregion #region 添加分数
public void Add(int Value)
{
Grade+=Value;
}
#endregion }

在这段代码中,Bullet是我们的子弹对象,它从飞机的两个子弹发射位置BulletPosL、BulletPosR发射,向屏幕上方依照一定的速度缓缓移动,当子弹与敌人碰撞时,子弹对象将销毁,同一时候敌人生命值降低。

Bullet对象相应于我们的一个Prefab。BulletPosL、BulletPosR相应于飞机上的两个位置。如图:

我们的子弹Bullet是一个绑定了脚本的Capsule。

它的代码定义例如以下:

using UnityEngine;
using System.Collections; public class Bullet : MonoBehaviour { //定义子弹的移动速度
public float MoveSpeed=10F;
//定义子弹的销毁时间
public float DestroyTime=2.0F;
//定义子弹对敌人的伤害值
public int Damage=2;
//玩家飞机
private GameObject Player; void Start()
{
Player=GameObject.Find("Player");
}
void Update ()
{
//移动子弹
transform.Translate(Vector3.up * MoveSpeed * Time.deltaTime);
} //碰撞事件捕捉
void OnTriggerEnter(Collider mCollider)
{
if(mCollider.gameObject.tag=="Enemy")
{
//敌人减血
mCollider.gameObject.GetComponent<Enemy>().Hit(Damage);
//我方得分
Player.GetComponent<Player>().Add(1);
//销毁子弹
Destroy(this.gameObject);
}
} //当离开摄像机范围时触发销毁事件
void OnBecameInvisible()
{
Destroy(this.gameObject);
}
}

三、敌人飞机

在我们的游戏中共同拥有三种敌机,我们先将它们制作成预设。

然后通过敌机生成器不断地生成敌机。

如图:

和子弹相反,我们希望敌机从屏幕上方以一定速度向下移动,当碰到玩家飞机或者子弹时,将降低生命值。为此,我们这样定义敌机的脚本:

using UnityEngine;
using System.Collections; public class Enemy : MonoBehaviour { //移动速度
public float MoveSpeed=1.5F;
//爆炸
public GameObject Explosion;
//最大生命值
public int MaxHP=100; void Update ()
{
//移动飞机
transform.Translate(Vector3.forward*Time.deltaTime*MoveSpeed);
} public void Hit(int Value)
{
//如血量不低于0。则敌人飞机掉血
if(MaxHP>0)
{
MaxHP-=Value;
}else
{
//产生爆炸效果
Instantiate(Explosion,transform.position,Quaternion.Euler(new Vector3(90,180,0)));
//销毁敌机
Destroy(this.gameObject);
}
} void OnTriggerEnter(Collider mCollider)
{
//假设与玩家飞机遭遇。则两方减血
if(mCollider.gameObject.tag=="Player")
{
//敌机掉血
this.Hit(2);
//玩家飞机掉血
Transform mPlayer=mCollider.gameObject.transform.Find("Player");
mPlayer.GetComponent<Player>().Hit(2);
}
} void OnBecameInvisible()
{
Destroy(this.gameObject);
}
}

接下来。我们通过敌机生成器来不断地生成敌机。

敌人生成器是我们预制在游戏场景中的空游戏体,它位于游戏场景的顶部。

我们将以下的脚本绑定到游戏生成器 上,使其能够不断地生成敌人:

using UnityEngine;
using System.Collections; public class SpawnEnemy : MonoBehaviour { //定义敌人速度
public float SpawnTime=1.0f;
//定义敌人对象数组
public GameObject[] Enemys; void Start ()
{
StartCoroutine("Spawn");
} //通过迭代器生成敌人
IEnumerator Spawn()
{
//等待
yield return new WaitForSeconds(SpawnTime);
//克隆对象
Instantiate(Enemys[Random.Range(0,3)],new Vector3(transform.position.x * Random.Range(-1F,1F),
transform.position.y,-4),Quaternion.Euler(new Vector3(90,180,0)));
StartCoroutine("Spawn");
} }

当中Enemys相应到我们的敌人预设,每隔一段时间,我们随机地产生一种敌人,该敌人将从屏幕上方缓缓向下移动。

四、碰撞检測

在这个游戏中。主要存在子弹与敌机的碰撞、玩家飞机与敌机的碰撞两种形式。

它们分别被定义在Bullet.cs和Enemy.cs两个类文件里。

//碰撞事件捕捉
void OnTriggerEnter(Collider mCollider)
{
if(mCollider.gameObject.tag=="Enemy")
{
//敌人减血
mCollider.gameObject.GetComponent<Enemy>().Hit(Damage);
//我方得分
Player.GetComponent<Player>().Add(1);
//销毁子弹
Destroy(this.gameObject);
}
}
void OnTriggerEnter(Collider mCollider)
{
//假设与玩家飞机遭遇。则两方减血
if(mCollider.gameObject.tag=="Player")
{
//敌机掉血
this.Hit(2);
//玩家飞机掉血
Transform mPlayer=mCollider.gameObject.transform.Find("Player");
mPlayer.GetComponent<Player>().Hit(2);
}
}

五、爆炸特效

当敌机被摧毁时,将显示爆炸特效,我们这里採用一组2D贴图来实现爆炸特效,原理是改变贴图的mainTextureScale和mainTextureOffset两个属性值。我们来一起看代码:

using UnityEngine;
using System.Collections; public class Explosion : MonoBehaviour { //动画序列索引
private int index=0;
//声音
private AudioSource mAudio; void Start()
{
mAudio=GetComponent<AudioSource>();
} void FixedUpdate ()
{
if(index<8)
{
this.renderer.sharedMaterial.mainTextureScale=new Vector2(1.0F/8,1);
this.renderer.sharedMaterial.mainTextureOffset=new Vector2(index * 1.0F/8,0);
index+=1;
}else
{
mAudio.Play();
Destroy(this.gameObject);
}
}
}

当中mAudio相应到一个AudioSource组件,我们在这里指定一个爆炸的音效。相同地,我们将爆炸制作成预设。该预设相应于Enemy.cs中的Explosion。

好了。到这里今天的 内容就解说完了,我们一起来看看终于的效果吧!

希望今天的内容大家能够喜欢。

学了这么长时间的Unity3D。感慨还是挺多的,非常多东西你不努力去做,是永远做不好的,你不给自己压力,你不会知道自己有多优秀。本项目源码能够从这里下载。

每日箴言: 无论活到什么岁数,总有太多思索、烦恼与迷惘。一个人假设失去这些。安于现状,才是真正意义上的青春的完结。——  渡边淳一

喜欢我的博客请记住我的名字:秦元培,我的博客地址是blog.csdn.net/qinyuanpei
      转载请注明出处,本文作者:秦元培,本文出处:http://blog.csdn.net/qinyuanpei/article/details/25158323

[Unity3D]Unity3D游戏开发之飞机大战项目解说的更多相关文章

  1. 关于《Unity3D/2D游戏开发从0到1》书籍再版说明

    关于<Unity3D/2D游戏开发从0到1>第一版本在2015年7月1日全国发行,累计得到不少国内高校教师.培训机构的好评.但是由于Unity官方对于技术不断的升级与版本的快速迭代,基于U ...

  2. 《Unity3D/2D游戏开发从0到1(第二版本)》 书稿完结总结

    前几天,个人著作<Unity3D/2D游戏开发从0到1(第二版)>经过七八个月的技术准备以及近3个月的日夜编写,在十一长假后终于完稿.今天抽出一点时间来,给广大热心小伙伴们汇报一下书籍概况 ...

  3. 《Unity3D/2D游戏开发从0到1》正式出版发行

    <Unity3D/2D游戏开发从0到1>正式出版发行 去年个人编写的Unity书籍正式在2015年7月正式发行,现在补充介绍一下个人著作.书籍信息:      书籍的名称: <Uni ...

  4. Unity3D 入门 游戏开发 Unity3D portal game development

    Unity3D 入门 游戏开发 Unity3D portal game development 作者:韩梦飞沙 Author:han_meng_fei_sha 邮箱:313134555@qq.com ...

  5. Unity3D手机游戏开发

    <Unity3D手机游戏开发> 基本信息 作者: 金玺曾 出版社:清华大学出版社 ISBN:9787302325550 上架时间:2013-8-7 出版日期:2013 年8月 开本:16开 ...

  6. Unity3D独立游戏开发日记(二):摆放建筑物

    在沙盒游戏里,能自由建造是很重要的特点,比如说风靡全球的<我的世界>,用一个个方块就能搭建出规模宏大的世界.甚至有偏激的人说,没有自由建造,就不是一个真正的沙盒游戏.的确,沙盒游戏的魅力有 ...

  7. Unity3D独立游戏开发日记(一):动态生成树木

    目前写的独立游戏是一个沙盒类型的游戏.游戏DEMO视频如下: 提到沙盒类型的游戏,就有人给出了这样的定义: 游戏世界离现实世界越近,自由度.随机度越高才叫沙盒游戏.所谓自由度,就是你在游戏里想干啥就干 ...

  8. 纯JavaScript开发飞机大战项目

    开发工具: HBuilder 编程语言:JavaScript 其他技术:Html + Css 项目截图:   视频:   源代码:   在线观看地址: (暂无) 百度网盘下载地址: 请加QQ群:915 ...

  9. Unity3D小游戏开发之两个我踩过的坑

    最近在开发一个植物大战僵尸小游戏,今天写了一早上的代码,踩了两个坑,这两个坑的位置分别位于触发器和数据转换,写这篇博文以此来让其他程序员不要再去踩这两个坑. 1.我在做简易僵尸模型的时候,这个僵尸模型 ...

随机推荐

  1. 在界面线程不能使用Sleep和WaitForSingleObject之类的函数, 使用 MsgWaitForMultipleObjects

    http://blog.csdn.net/wishfly/article/details/3726985 你在主线程用了WaitForSingleObject,导致了消息循环的阻塞,界面假死. 然后在 ...

  2. Android Studio之同一窗口打开项目

    Android Studio默认新打开的项目都是重新打开一个窗口,和原项目窗口同时存在,如果打开多个项目,则有很多窗口同时打开,怎么根据需要决定自己以何种方式打开呢? 1.设置打开新项目的方式 第一项 ...

  3. select value from v$diag_info where name='Default Trace File';

    VALUE -------------------------------------------------------------------------------- /u01/diag/rdb ...

  4. [置顶] 深圳华为BSS公共部件 (BI 商业智能 Java Javascript)

    深圳华为BSS公共部件 部门招聘 招聘面试地点:大连,西安 工作地点:深圳 时间:2013年9月7日 联系方式:dawuliang@gmail.com 18675538182 有兴趣的同学,可以直接电 ...

  5. uva 1151 - Buy or Build poj 2784 Buy or Build(最小生成树)

    最小生成树算法简单 只是增加了一些新的东西,对于需要最小生成树算法 和中 并检查使用的一系列 还有一些更深入的了解. 方法的一些复杂问题 #include<cstdio> #include ...

  6. ThinkPHP连接数据库出现的错误:Undefined class constant 'MYSQL_ATTR_INIT_COMMAND'

    最近看了看ThinkPHP.在连接mysql数据库时出现了错误:Undefined class constant 'MYSQL_ATTR_INIT_COMMAND'.意思就是没有PDO(PHP数据对象 ...

  7. Java中替代C# ref/out 关键字方案:

    刚学习Java不久,今天遇到一个问题,需要在方法中修改传入的对象的值,确切的说是需要使用一个方法,创建一个对象,并把其引用返回,熟悉C#的我的第一反应就是C#中的ref/out关键字,结果发现Java ...

  8. eclipse package,source folder,folder差别及相互转换

    在eclipse下, package, source folder, folder都是目录.   它们的差别例如以下:   package:当你在建立一个package时,它自己主动建立到source ...

  9. Tiny并行计算框架之复杂演示样例

    问题来源  很感谢@doctorwho的问题: 假如职业介绍所来了一批生产汽车的工作,如果生产一辆汽车任务是这种:搭好底盘.拧4个轮胎.安装发动机.安装4个座椅.再装4个车门.最后安装顶棚. 之间有的 ...

  10. 2014年百度之星程序设计大赛 - 资格赛 第二题 Disk Schedule

    双调欧几里得旅行商问题是一个经典动态规划问题.<算法导论(第二版)>思考题15-1和北京大学OJ2677都出现了这个题目. 旅行商问题描写叙述:平面上n个点,确定一条连接各点的最短闭合旅程 ...