Unity3D游戏开发初探—4.开发一个“疯狂击箱子”游戏
一、预备知识—对象的”生“与”死“
(1)如何在游戏脚本程序中创建对象而不是一开始就创建好对象?->使用GameObject的静态方法:CreatePrimitive()
以上一篇的博文中的“指哪打哪”例子为基础,在AddForce脚本写入以下代码:
void Update()
{
// Demo3:点击鼠标左键自动创建Cube对象
if (Input.GetMouseButtonDown())
{
CreateCube();
}
} void CreateCube()
{
GameObject goCube = GameObject.CreatePrimitive(PrimitiveType.Cube);
goCube.transform.position = new Vector3(, , );
goCube.AddComponent<Rigidbody>();
}
其中在CreateCube方法中,使用GameObject.CreatePrimitive方法来创建Cube类型的游戏对象实例,设置了它出现的坐标并为它增加刚体组件。这里可以看下AddComponent方法,它的参数是一个泛型,也就是说我们在属性面板中看到的那些组件,例如刚体、音频源甚至脚本等组件对象都可以通过AddComponet方法来动态地添加。现在来看看在游戏中点击鼠标左键创建Cube对象的效果:
(2)细心的读者会发现,当我们创建了无数个Cube对象之后,计算机的内存占用率会逐步上升。机智的你肯定会想到,适时销毁创建的游戏对象,释放内存资源。不要担心,Unity3D为我们提供了一个非常方便的方法:Destroy()。这个函数提供了两个重载:第一个你可以直接传递一个游戏对象的ID(比如我们在上个例子中创建了一个Plane,它的ID也为Plane);第二个你可以传递两个参数,一个是刚刚提到的游戏对象的ID,另一个是延迟销毁的秒数(也就是说可以在规定的秒数之后再从屏幕中消失,从内存中销毁);
下面我们重新修改一下刚刚的AddForce脚本为如下代码:
void Update()
{ // Demo4:点击鼠标左键自动销毁Plane对象
if(Input.GetMouseButtonDown())
{
DestroyGameObject("Plane");
}
} void DestroyGameObject(string objectName)
{
GameObject goCube = GameObject.Find(objectName);
// 延时2秒之后才销毁该对象
Destroy(goCube, );
}
这里我们将销毁游戏对象的代码封装成了一个方法:DestroyGameObject(),它首先通过GameObject.Find方法找到指定ID的游戏对象,然后调用销毁游戏对象的方法Destroy将其销毁掉,这里使用了第二个重载,为其传递了一个2秒的延迟时间。也就是说,当我们点击鼠标左键后2秒,Plane对象才会被销毁,我们的Sphere球体对象便会跌落深渊!现在我们来看看效果如何:
在预览效果的同时,你可以观察左侧Hierarchy中的对象列表,Plane在什么时刻消失了?
好了,预备知识到此结束,现在我们真正开始CrazySphere(简称:CS,听起来高大上吧,么么嗒!)—“疯狂击箱子”游戏的开发之旅!
二、疯狂击箱子—CrazySphere的实现之路
既然我们的“CS”是击箱子,木有箱子怎么能行呢!现在,我们就来创建一些箱子,作为我们击打的对象。
首先,考虑到要初始化的箱子足足有16个,我们需要在程序中来创建这些箱子,并将它们放在Plane中,组成箱子墙,让我们的小球来击打。
(1)在Hierarchy中Create以下对象:一个Direction Light,一个Plane;将Plane的Position设置为(0,1,-6),这样看起来清楚一点;
(2)准备工作:
①在Assets中Create以下文件夹(Folder):一个Images文件夹用来存放贴图文件,一个Musics文件夹用来存放背景音乐和音效MP3,一个Scripts文件夹用来存放C#脚本文件,见下图所示:
②往Images里边导入一些贴图,我这里在网上找了几张愤怒的小鸟的图片,用来给Plane、Sphere以及Cube对象做渲染材质贴图,这样游戏对象看起来好看一点。(具体的文件请下载附件中的源码,找到Assets/Images/)
③往Musics里边导入一首背景音乐和一首音效文件,背景音乐作为游戏背景音乐默认且循环播放,音效音乐作为小球冲击箱子的音效在小球发出时播放。这里背景音乐我选择的是萨克斯经典—回家,是不是很文艺?音效呢,我就上网随便找了个炮弹发射的音效。(具体的文件请下载附件中的源码,找到Assets/Musics/)
然后,选中Hierarchy中的Main Camera,选择主菜单栏中的Component->Audio->Audio Source,在属性中的Audio Source块中选择导入的背景音乐(这里是GoHome-Sax),并勾选Play On Awake(是否默认播放)以及Loop(是否循环播放)复选框,我们在游戏一开始时就会播放GoHome-Sax.mp3文件。
最后,按照上面的步凑为Plane增加Audio Source,将其选择为Bomb作为初始化音效。
④在Scripts中Create两个C# Script,一个命名为InitScene,另一个命名为AutoDestroy。InitScene脚本用于初始化游戏场景,也就是4*4的箱子矩阵。而AutoDestroy脚本则用于销毁超出主摄像机可视范围的游戏对象,也就是当我们的小球或被击中的箱子超出Plane的地面范围或跌落后就将其自动销毁。
(3)首先来编写AutoDestroy脚本,利用我们在 预备知识 里边学到的自动销毁对象的方法。这个AutoDestroy脚本是需要附加到需要自动销毁的游戏对象上才会有意义,所以后边会在初始化场景的主脚本中为自动创建的对象附加此脚本(利用AddComponent提供的泛型方法)。
using UnityEngine;
using System.Collections; public class AutoDestroy : MonoBehaviour
{ // Use this for initialization
void Start()
{ } // Update is called once per frame
void Update()
{ } // 当离开摄像头可视范围时触发的事件
void OnBecameInvisible()
{
// 销毁当前游戏对象
Destroy(this.gameObject);
}
}
PS:OnBecameInvisible()方法是Unity3D中自带的方法,它在具体的游戏对象在游戏屏幕上不可见时触发。你可以理解它就类似于ASP.NET WebForm中Global文件中的Application_End()事件。这里,我们在游戏对象不可见时,销毁具体的游戏对象。注意,这里销毁的方法参数是this.GameObject而不是this!
(4)现在我们来编写InitScene脚本,这个是重点!编写完成后,把此脚本附加到Main Camera对象中!
using UnityEngine;
using System.Collections; public class InitScene : MonoBehaviour
{
private GameObject goPlane; // Use this for initialization
void Start()
{
// 获取Plane对象
goPlane = GameObject.Find("Plane");
// 初始化4*4个箱子群
CreateCubes();
} void CreateCubes()
{
// 创建4*4个Cube立方体作为箱子
for (int i = ; i < ; i++)
{
for (int j = ; j < ; j++)
{
GameObject goCube = GameObject.CreatePrimitive(PrimitiveType.Cube);
goCube.transform.position = new Vector3(i - , j, -);
// 增加刚体组件使其具有重力
goCube.AddComponent<Rigidbody>();
// 增加脚本使对象自动销毁
goCube.AddComponent<AutoDestroy>();
// 增加渲染贴图
goCube.renderer.material.mainTexture =
Resources.LoadAssetAtPath("Assets/Images/CubeImage.jpg", typeof(Texture)) as Texture;
}
}
} // Update is called once per frame
void Update()
{
// 控制Sphere朝着鼠标指定的坐标发起冲击
if (Input.GetMouseButtonDown())
{
// 创建要发出的小球Sphere
GameObject goBullet = GameObject.CreatePrimitive(PrimitiveType.Sphere);
goBullet.transform.position = Camera.main.transform.position;
goBullet.AddComponent<Rigidbody>();
goBullet.AddComponent<AutoDestroy>();
goBullet.renderer.material.mainTexture =
Resources.LoadAssetAtPath("Assets/Images/AngryBird.jpg", typeof(Texture)) as Texture; // 获取目标位置的世界坐标
Vector3 targetPos = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x,
Input.mousePosition.y, ));
Vector3 dirPos = targetPos - Camera.main.transform.position; // 进击吧!疯狂的小球!
goBullet.rigidbody.AddForce(dirPos * , ForceMode.Impulse); // 播放爆炸音效
goPlane.GetComponent<AudioSource>().Play();
}
} }
现在我们一一来分析这段脚本代码:
①CreateCubes()方法定义了初始化4*4个箱子的实现过程,每循环一次通过CreatePrimitive创建Cube类型的立方体,然后为每个立方体设置position坐标、增加刚体组件、增加脚本使其能够自动销毁以及为其渲染贴图。
②在Update()方法中控制小球朝着鼠标指定的坐标发起冲击:当用户点击鼠标左键时即刻创建一个Sphere小球,仍然是设置坐标、增加刚体组件、渲染贴图、增加脚本使其能够自动销毁。这里需要注意的是,小球的坐标应该为摄像头的位置,因为小球是从摄像头飞出去的。然后,通过屏幕坐标向世界坐标的转换获取目标向量,再通过目标所在向量-摄像头所在向量=方向向量(这里涉及到向量减法,不明白的读者可以看看本文第二篇3D模型基础,或者去复习下高中向量减法的几何意义)。最后,为小球添加一个往鼠标点击的方向的多大的力,它就会往那个方向去走(这里是“飞“)。为了突出效果,这里还为小球添加了音效效果,在发出时播放。
(5)到这里,一个基本的CrazySphere就可以实现了,现在我们来看下效果:可以让小球按照我们制定的坐标发射,发射时还会有炮弹的音效,而且背景音乐一直在循环播放着,一个demo就差不多完成了,是不是很快!
(6)但是大家是否觉得我们的游戏背景太单调了,没关系,Unity3D为我们提供了Skyboxes-天空盒子,让我们的背景一秒变为灿烂的蓝天!(有关天空盒子的详细内容请参阅参考文献中关于天空盒子的介绍,这里不再阐述)这里我们向场景中添加一个Sunny的天空盒子:
①在Assets处单击鼠标右键,选择Import Package->Skyboxes,在弹出的选择框中选择Sunny1的mat、与Sunny1有关的tif资源。这里注意不要将全部的天空盒子都导进来,那样文件会很大!
②点击主菜单栏Edit->Render Settings,在右侧的属性栏中找到Skybox Material:
单机右侧的选择按钮,在弹出的选择框中即可看到我们刚刚导入的Sunny1这个天空盒子,双机选中它,这样我们就让游戏背景一秒变为阳光灿烂的蓝天,是不是心旷神怡啊!
(6)现在,我们再来看看游戏效果:是不是变为蓝天啦?这样,我们的CrazySphere v1.0就开发好了!
三、总结
通过几天的Unity3D初探学习,我们学习了Unity3D的基本知识、3D模型基础、物理引擎基础,并综合这些知识做了一个小游戏:CrazySphere-疯狂击箱子的游戏,还实现了背景音乐、音效效果的播放,加入天空盒子让游戏背景好看。当然,本系列作为初探,不可能学的很深入,但至少我们可以入门,可以初步领略到Unity3D的强大魅力以及我们.NET程序员的学习优势。
不知不觉之间,已经写了四篇关于Unity3D的学习笔记了,同时这也是我的第一个系列的博文,对我的博客生涯具有重要的意义,再次感谢给我鼓励的园友们,让我作为一个新人倍感荣幸。另外,本文是基于传智播客的Unity3D的两次公开课为基础,整理而成的,衷心感谢传智播客以及杨中科的分享,还有老杨的鼓励。马上就要开学了,又要回成都了,苦逼的研究生生涯还得继续,好想早点毕业啊!被学校派到外边实习,老师(实验室指导老师,非我的导师,我的导师还是蛮不错的)也不准时发工资,每天还干的累死累活的。但是,还是想在此祝愿各位园友码年吉祥,2014越码越健康!
明天就是我外婆70岁的生日了,在此也祝愿她老人家生日快乐,身体健康!
本文最后会附上本次小游戏案例的Demo文件供下载,里面有本次用到的所有素材。另外,该Demo中还使用了GUI自定义了鼠标显示,将鼠标显示替换为一张瞄准星的贴图,如下图所示:
参考文献与资料
(1)传智播客Unity3D公开课:http://net.itcast.cn/subject/Unity3D/index.html
(2)XieXuan2007,《Unity3D天空盒》:http://blog.csdn.net/xiexuan2007/article/details/18401075
(3)丁小未,《Unity3D开发类似保龄球游戏》:http://blog.csdn.net/dingxiaowei2013/article/details/9734935
附件
Demo文件下载:https://github.com/EdisonChou/CrazySphere
Unity3D游戏开发初探—4.开发一个“疯狂击箱子”游戏的更多相关文章
- 基于Unity的AR开发初探:第一个AR应用程序
记得2014年曾经写过一个Unity3D的游戏开发初探系列,收获了很多好评和鼓励,不过自那之后再也没有用过Unity,因为没有相关的需求让我能用到.目前公司有一个App开发的需求,想要融合一下AR到A ...
- 【浅墨Unity3D Shader编程】之中的一个 夏威夷篇:游戏场景的创建 & 第一个Shader的书写
本系列文章由@浅墨_毛星云 出品.转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/40723789 作者:毛星云(浅墨) ...
- JavaScript写一个小乌龟推箱子游戏
推箱子游戏是老游戏了, 网上有各种各样的版本, 说下推箱子游戏的简单实现,以及我找到的一些参考视频和实例: 推箱子游戏的在线DEMO : 打开 如下是效果图: 这个拖箱子游戏做了移动端的适配, 我使用 ...
- 剑指XX(游戏10) - 走正步工厂一个安静的农场游戏的代码
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2lsYW5ncXVhbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...
- 如何做出一个好的c++游戏
目录 一.游戏分类 1.文字型 2.画图型 3.键盘型 二.游戏创意 你的程序可以比较激情.热血 1.打怪,爆装备型 2.答题闯关型 可以添加一些不可思议的物品和玩法 三.学号c++/c的语法,是成功 ...
- 💒 es6 + canvas 开源 盖楼小游戏 完整代码注释 从零教你做游戏(一)
盖楼游戏 一个基于 Canvas 的盖楼游戏 Demo 预览 在线预览地址 (Demo Link) 手机设备可以扫描下方二维码 github https://github.com/bmqb/tower ...
- Unity3D游戏开发初探—1.跨平台的游戏引擎让.NET程序员新生
一.Unity3D平台简介 Unity是由Unity Technologies开发的一个让轻松创建诸如三维视频游戏.建筑可视化.实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的 ...
- Unity3D游戏开发初探—2.初步了解3D模型基础
一.什么是3D模型? 1.1 3D模型概述 简而言之,3D模型就是三维的.立体的模型,D是英文Dimensions的缩写. 3D模型也可以说是用3Ds MAX建造的立体模型,包括各种建筑.人物.植被. ...
- Unity3D游戏开发初探—3.初步了解U3D物理引擎
一.什么是物理引擎? 四个世纪前,物理学家牛顿发现了万有引力,并延伸出三大牛顿定理,为之后的物理学界的发展奠定了强大的理论基础.牛顿有句话是这么说的:“如果说我看得比较远的话,那是因为我站在巨人的肩膀 ...
随机推荐
- 高性能的JavaScript--数据访问(1)
写在前面 数据存储在哪里,关系到代码运行期间数据被检索到的速度.在JavaScript中,此问题相对简单,因为数据存储只有少量方式可供选择.正如其他语言那样,数据存储位置关系到访问速度.在JavaSc ...
- Asp.net中延长session失效时间(2点注意web.config和IIS)
一个是软件系统中的web.config: 配置文件web.config 的<system.web>下加上<sessionState mode="InProc" ...
- d3 中exit() remove()正确工作的方式
在官网中给出的代码[1]是有问题的,如下的代码并不能正常工作: // Update… var p = d3.select("body").selectAll("p&quo ...
- 机器学习之K-近邻算法
机器学习可分为监督学习和无监督学习.有监督学习就是有具体的分类信息,比如用来判定输入的是输入[a,b,c]中的一类:无监督学习就是不清楚最后的分类情况,也不会给目标值. K-近邻算法属于一种监督学习分 ...
- selenium使用Xpath定位之完整篇
其中有一片文章提到了xpath元素定位,但是该文章中有些并不能适应一些特殊与个性化的场景.在文本中提供xpath元素的定位终极篇,你一定能在这里找到你需要的解决办法. 第一种方法: 通过绝对路径做定位 ...
- BZOJ3438 小M的作物(最小割)
题目 Source http://www.lydsy.com/JudgeOnline/problem.php?id=3438 Description 小M在MC里开辟了两块巨大的耕地A和B(你可以认为 ...
- python基础04 运算
数学运算 print 2+2 #加法 print 1.3-4 #剪法 print 3*5 #乘法 print 4.5/1.5 #除法 print 3**2 #乘方 print 10%3 #求 ...
- Linux查看系统状态命令
Linux查看系统状态命令 iostat iostat 命令详细地显示了存储子系统方面的情况.你通常用iostat来监控存储子系统总体上运行状况如何,并且在用户注意到服务器运行缓慢之前提早 ...
- storm 入门原理介绍
1.hadoop有master与slave,Storm与之对应的节点是什么? 2.Storm控制节点上面运行一个后台程序被称之为什么? 3.Supervisor的作用是什么? 4.Topology与W ...
- STM32之ADC+步骤小技巧(英文)
神通广大的各位互联网的网友们.大家早上中午晚上好好好.今早起来很准时的收到了两条10086的扣月租的信息.心痛不已.怀着这心情.又开始了STM32的研究.早上做了计算机控制的PID实验,又让我想起了飞 ...