Unity3D实践系列06,球体撞击物体游戏
本篇实现一个球体在固定区域移动撞击Cube的游戏。

首先有1个Plane当作地面,1个Sphere当作球体,4个Cube当作墙,12个Cube当作被撞击物体,另外还有球体的撞击计算,在撞击的过程适时显示撞击的球体数,12个Cube被撞击后提示游戏结束。
创建项目,创建背景和球
创建一个项目,名称为"MyRollBall",选择项目所在文件,选择"3D"项,点击"Create project"。
点击"File"菜单下的"Save Scene",在"MyRollBall"项目下的"Asserts"中创建一个自定义文件夹,名称是"_MyScene",然后把保存的Scene命名为"MiniGame",并保存到"_MyScene"文件夹中。创建完后,在"Project"窗口下的文件结构如下:

依次点击"GameObject"菜单下的"3D object","Plane",并在"Hierarchy"窗口中重命名为"Ground"。
点击"Hierarchy"窗口中的"Ground",在"Scene"窗口中,Ground自动调整到"Scene"窗口的中心;在"Inspector"窗口的"Transform"中有一个"Reset"按钮,点击它,会把这里的Ground恢复到初始状态;点击"Edit"菜单下的"Frame Selected"会看到"Scene"窗口的整个画面。
此时,"Scene"窗口的背景呈网格状,这里需要隐藏网格。点击"Scene"窗口"Gizmos"下拉项,把"Show Grid"的勾选去掉。
改变Ground的缩放比例,可以通过如下3种方式的一种来做:
1、点击"Hirarchy"窗口中的Ground,按快捷键R,通过拖动"Scene"窗口中Ground的x,z轴来实现。
2、点击"Hirarchy"窗口中的Ground,无需按哪个视图快捷键,把鼠标移上"Inspector"窗口中,"Transform"下的"Scale"中的"X"字母或"Z"字母上,通过鼠标的左右滑动来改变缩放。
3、直接修改"Inspector"窗口中,"Transform"下的"Scale"中"X"和"Z"的属性值。
注意:这里的Ground,即类型为"plane"的GameObject,沿y轴方向正向调整不会影响Ground的可见性,一旦拖动Y轴,让Y轴对应的值为负值,Ground随即不可见。这里给我们的启示是:如果一个GameObject不可见,我们可以调整该GameObject的Y值,来使其可见。
现在再增加一个球体。在"GameObject"菜单栏的"3D Object"中选择"Sphere",在"Hierarchy"窗口为Sphere重命名为"Player"。
在保证"Hierarchy"窗口为Sphere为选中状态下,点击"Edit"菜单下的"Frame Selected",Sphere在Scene窗口中出现在焦点位置,并呈选中状态。

但是,我们发现球体的位置不太对,所以要调整球体的位置。拖动"Scene"窗口中Sphere的y轴,使其往上移动,让整个球体在水平面之上。当然调整"Inspector"中的相关属性也是可以的。
在"Project"下的"Asserts"中添加名称为"Materials"的Folder。
选中"Mateirals"这个Folder,右键,依次选择"Create","Material",这样在"Mateirals"这个Folder中添加了一个名称为"New Mateiral"的Material,并重命名为"Background"。
修改名称为"Background"的"Inspector"窗口中的"Albedo"项,修改RGB属性值为"0,32,64",可以在"Inspector"窗口的最下方预览到效果。接着拖动这里的"Background"到"Scene"窗口的"Ground"上面,"Ground"因此有了Material。

点击"Hierarchy"窗口下的"Directional Light",修改"Inspector"窗口中"Rotation"的"Y"为60。
移动球
在"Hierarchy"窗口中选择名称为"Player"的GameObject。
为了能够让名称为"Player"的GameObject运动,需要为其添加"RigidBody"。
依次选择"Component"菜单、"Physics"、"RigidBody",之后,在"Inspector"窗口多了一个"Rigidbody"组件。当然,为GameObject添加组件Compnenet的方式不止这一种,可以点击"Inspector"窗口的"Add Component"按钮。还可以在"Inspector"窗口中调整各个组件的顺序。还可以折叠或展开各个组件面板。
选中"Project"下的"Asserts",添加一个"Scripts"文件夹。
再次选中"Hierarch"中的"Player",在其对应的"Inspector"窗口中点击"Add Component"按钮,点击"New Script",命名为"PlayerController"。按这种方式添加的脚本自动附加到GameObject上了。而在"Asserts"下也多了一个名称为"PlayerController"的脚本,为了把文件夹组织得更好,把该脚本拖入刚创建的"Scripts"文件夹。
双击脚本,在Visutal Studio中打开,编辑如下:
using UnityEngine;using System.Collections;public class PlayerController : MonoBehaviour{public float speed;private Rigidbody rb;void Start (){rb = GetComponent<Rigidbody>();}void FixedUpdate(){float moveHorizontal = Input.GetAxis("Horizontal");float moveVertical = Input.GetAxis("Vertical");Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);rb.AddForce(movement * speed);}// Update is called once per framevoid Update () {}}
可以在官网查看到所有的API:http://docs.unity3d.com/ScriptReference
再次点击"Hirarchy"下的"Player",在其对应的"Inspector"窗口下的"Player Controller"这个脚本中,调整Speed的属性值,设置为100。
运行。
按动键盘方向键,球以某种速度移动起来。
移动Camera
现在想把Camera附加到球体上。
首先设置Camera的位置。
在MainCamera对应的"Inspector"窗口中,在"Transform"下,调整"Position"的x,y,z分别为"0,10,-10",调整"Rotation"的x,y,z分别为"45,0,0",再在"Hierarchy"窗口中把"Main Camera"拖动到"Player"上,使其成为"Player"的一个子GameObject。这意味着当球体移动的时候,Camera也会跟着移动。
再次运行,这次看到球体移动非常快,这是因为Camera的位置相对于球体变化了。
在"Hierarch"窗口中,把"Main Camera"移动出"Player",不要让其成为球体的子GameObject。
为"Main Camera"添加一个名称为"CameraController"的脚本,编辑如下:
using UnityEngine;using System.Collections;public class CameraController : MonoBehaviour {//说明这个Camera指向于某一个Gameobject,在这里是球体public GameObject player;//Camera的偏移量private Vector3 offset;void Start(){//Camera的位置-球体的位置offset = transform.position - player.transform.position;}void LateUpdate(){//让Camera根据球体的位置获得一个新位置transform.position = player.transform.position + offset;}}
好,现在要把球体赋值给Camera。先打开"Main Camera"对应的"Inspector"窗口,然后拖动"Hierarchy"窗口下的名称为"Player"的球体到"Inspector"中"Camera Controller"中"Player"这个属性框上。
运行,这时,球在运动的时候有了一个很好的Camera角度。
设置球体运动区域
为了放置球体在移动过程中掉落,我们需要设置球体的运行区域。
创建一个空的"Game Object",并重命名为"Walls",并把之设置为默认值。
创建一个"Cube"类型的"Game Object",并重命名为"West Wall",并把之设置为默认值,拖动使其成为空"Game Object"的子项。
现在,"Scene"窗口中呈现出如下的位置关系。

这时需要调整Cube的位置,依次创建4个Cube,从4个方向挡住球体。
再次运行,球体被牢牢困在4个cube中间。
创建被球体撞击的物体
创建一个Cube类型的GameObject,重命名为"Pickup",设置其默认值,点击"Edit"菜单中的"Frame Selected"使其成为"Scene"窗口的焦点。
按如下设置"Pickup"的"Transform"。

现在想为其增加旋转效果。为其专门创建一个名称为"Rotator的脚本"。
using UnityEngine;using System.Collections;public class Rotator : MonoBehaviour {// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {transform.Rotate(new Vector3(15, 30, 45) * Time.deltaTime);}}
运行,"Pickup"会不停地旋转。
在"Project"窗口中,在"Asserts"下创建"Prefabs"文件夹。
把"Hierarchy"中的"Pickup"拖动到"Prefabs"文件夹中。
创建一个空的GameObject,重命名为"Pickups",设置默认值。
把"Asserts"中"Prefabs"中的"Pickup"拖动到"Pickups"中,作为子GameObject。
选中"Hierarchy"窗口中的"Pickup",选择左上角的"Local"模式,拖动"Pickup"到一个合适的位置。
复制"Pickup"12个,围成一个圈。
在"Project"窗口中的"Material"文件夹中再复制一个,重命名为"Pickup",改变其颜色为黄色。
把其拖动到"Scene"窗口中的各个"Pickup",这时,所有的"Pickup"呈现为黄色。
撞击物体
修改脚本"PlayerController"。
using UnityEngine;using System.Collections;public class PlayerController : MonoBehaviour{public float speed;private Rigidbody rb;void Start (){rb = GetComponent<Rigidbody>();}void FixedUpdate(){float moveHorizontal = Input.GetAxis("Horizontal");float moveVertical = Input.GetAxis("Vertical");Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);rb.AddForce(movement * speed);}//Collider表示被球体碰撞的其它物体void OnTriggerEnter(Collider other){if (other.gameObject.CompareTag("Pick Up")){other.gameObject.SetActive(false);}}// Update is called once per framevoid Update () {}}
回到Unity界面,选择"Project"界面上"Prefabs"文件夹内的"Pickup",在"Inspector"窗口加添加"Pick Up"标签。
运行,控制键盘方向键,当物体碰撞到Cube上的时候,Cube没有消失。这不是我们所期望的。
回到Unity界面,选择"Project"界面上"Prefabs"文件夹内的"Pickup",在"Inspector"窗口,在"Box Collider"中,勾选"Is Trigger"。
运行,控制键盘方向键,当物体碰撞到Cube上的时候,Cube消失。这正是我们所期望的。
所有的带Rigid Body的Game Object被Unity理解为dynamic,不带Rigid Body的Game Object被Unity理解成为static。如果没有把Game Object附加Rigid Body的话,Unity在每一帧都会统计这些static Game Object,这非常消耗资源。所以,我们应当为Game Object附加Rigid Body,让其变成dynamic。static是不可以移动的,而dynamic是可以移动的。
回到Unity界面,选择"Project"界面上"Prefabs"文件夹内的"Pickup",在"Inspector"窗口,点击"Add Component"按钮,为其添加Rigid Body组件。
再次运行,发现所有的Cube消失了,为什么?
回到Unity界面,选择"Project"界面上"Prefabs"文件夹内的"Pickup",在"Inspector"窗口,把"Rigid Body"中"Use Gravity"的勾选去掉。
再次运行,正常运行。
显示分数
在"Hierarch"窗口中添加Text,Text作为Canvas的子Game object出现,并重命名为"Counter Text"。选择Text,改变其字体颜色为白色,同时按住"alt"+"shift"键,改变Text的位置。
在"Hierarch"窗口中添加Text,Text作为Canvas的子Game object出现,并重命名为"Win Text"。选择Text,改变其字体颜色为白色。
修改"PlayerController"脚本。
using UnityEngine;using System.Collections;using UnityEngine.UI;public class PlayerController : MonoBehaviour{public float speed;public Text countText;public Text winText;private Rigidbody rb;private int count;void Start(){rb = GetComponent<Rigidbody>();count = 0;SetCountText();winText.text = "";}void FixedUpdate(){float moveHorizontal = Input.GetAxis("Horizontal");float moveVertical = Input.GetAxis("Vertical");Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);rb.AddForce(movement * speed);}void OnTriggerEnter(Collider other){if (other.gameObject.CompareTag("Pick Up")){other.gameObject.SetActive(false);count = count + 1;SetCountText();}}void SetCountText(){countText.text = "击中了: " + count.ToString() + "个";if (count >= 12){winText.text = "成功!";}}}
把"Hierarchy"窗口中,"Canvas"下的Text拖拽到"Player"球体对应的"Inspector"窗口内的"Counter Text"和"Win Text"属性值框上。
Build游戏
选择"File"菜单下的"Build Settings"。
点击"Add Current"按钮,把当前的"Scene"添加进来。

点击"Build"按钮。保存.exe文件保存到某个位置。
运行可执行文件,即看到与Unity软件中一样的效果。
参考资料:https://unity3d.com/learn/tutorials/projects/roll-a-ball/moving-the-camera
Unity3D实践系列06,球体撞击物体游戏的更多相关文章
- Unity3D实践系列04, 脚本的生命周期
Unity3D脚本生命周期是指从脚本的最初唤醒到脚本最终销毁的整个过程.生命周期的各个方法被封装到了MonoBehaviour类中.具体来说如下: 1.In Editor Mode 编辑模式 当在编辑 ...
- Unity3D实践系列07,组件的启用或禁用开关,物体的的可见或不可见开关,以及相应事件
创建一个Unity项目. 在"Project"窗口中,在"Asserts"中,添加"_MyScene"文件夹. 点击"File&q ...
- Unity3D实践系列02,查看Scene窗口物体
删除"Hierarchy"窗口中的"Directional Light". 把鼠标放在"Scene"窗口,滑动鼠标滚轮,可以对"S ...
- Unity3D实践系列09, 物理引擎与碰撞检测
在Unity3D中,一个物体通常包含一个Collider和一个Rigidbody.Collider是碰撞体,一个物体是Collider,才可以进行碰撞检测.Collider组件中的"Is T ...
- Unity3D实践系列08, MonoBehaviour类的各种触发事件
在脚本的生命周期中,有Awake, Start, FixedUpdate, Update, LateUpdate等方法,其实这些属于MonoBehaviour类的事件响应方法,是MonoBehavio ...
- Unity3D实践系列03,使用Visual Studio编写脚本与调试
在Unity3D中,只有把脚本赋予Scene中的GameObject,脚本才会得以执行. 添加Camera类型的GameObject. Unity3D默认使用"MonoDevelop&quo ...
- Unity3D实践系列11, 组件的添加和访问
当把一个脚本附加到一个GameObject上的时候,这个GameObject就有了脚本组件. 通过GameObject的属性获取组件 比如如下: [RequireComponent(typeof(Ri ...
- Unity3D实践系列10, Canvas画布的创建和使用
Canvas是所有ui元素的父物体. 当添加一个Button类型的GameObject后,在"Hierarch"窗口中自动添加了一个Canvas,以及EventSystem. 在C ...
- Unity3D实践系列05,为GameObject添加额外属性
在Unity中,通常通过脚本为GameObject添加额外的属性.具体有2种方式:一种是通过硬编码为脚本字段赋值,另一种是通过反射在运行时给脚本字段赋值. 脚本通过字段硬编码为GameObject添加 ...
随机推荐
- 利用gcc自带的功能-fstack-protector检测栈溢出及其实现【转】
转自:https://www.cnblogs.com/leo0000/p/5719186.html 最近又遇到了一个崩溃,栈回溯非常怪异. /lib/i386-linux-gnu/libc.so.6( ...
- Linux字符集的查看及修改【转】
一·查看字符集字符集在系统中体现形式是一个环境变量,以CentOS6.5为例,其查看当前终端使用字符集的方式可以有以下几种方式: 1.[root@david ~]# echo $LANGzh_CN.G ...
- how-to-pass-a-class-variable-to-a-decorator-inside-class-definition
https://stackoverflow.com/questions/17522706/how-to-pass-a-class-variable-to-a-decorator-inside-clas ...
- 为你详细解读HTTP请求头的具体含意
当我们打开一个网页时,浏览器要向网站服务器发送一个HTTP请求头,然后网站服务器根据HTTP请求头的内容生成当次请求的内容发送给浏览器.你明白HTTP请求头的具体含意吗?下面一条条的为你详细解读,先看 ...
- 关于Spring 事务管理传播属性的配置及作用-嵌套事务
先了解事务的7种传播属性: PROPAGATION_REQUIRED -- 支持当前事务,如果当前没有事务,就新建一个事务.这是最常见的选择. PROPAGATION_SUPPORTS -- 支持当前 ...
- 002_分布式搜索引擎Elasticsearch的查询与过滤
一.写入 先来一个简单的官方例子,插入的参数为-XPUT,插入一条记录. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 curl -XPUT 'http:/ ...
- yum安装软件报错:curl#6 - "Could not resolve host: mirrorlist.centos.org; Temporary failure in name resolut
# yum install -y epel-release Loaded plugins: fastestmirror Repository base is listed more than once ...
- 浅谈js设计模式之迭代器模式
迭代器模式无非就是循环访问聚合对象中的各个元素.比如 jQuery中的 $.each 函数,其中回调函数中的参数 i 为当前索引, n 为当前元素,代码如下: $.each([1, 2, 3], fu ...
- 使用Golang编写优化算法 (1)
动手写点东西是学习新知识很重要的一个阶段.之前用 Python 和 JavaScript 实现优化算法,现在用 Golang 来实现.语法上略有不爽,某些C语言的思维又回来了. - Golang 用 ...
- GMM实战
一道作业题: https://www.kaggle.com/c/speechlab-aug03 就是给你训练集,验证集,要求用GMM(混合高斯模型)预测 测试集的分类,这是个2分类的问题. $ hea ...