unity3d 炮弹怎么制作炮弹打

建立一个炮弹
进入编辑器
1 using UnityE
2 using System.C
4 public class acc : MonoBehaviour {
// Use this for initialization
public Transform Q;
int speed=50;
void Start () {
// Update is called once per frame
void Update () {
float x = Input.GetAxis("Horizontal") * Time.deltaTime *//左右移动
float z = Input.GetAxis("Vertical") * Time.deltaTime *//
//主摄像机物体
transform.Translate(x,0,z);
if(Input.GetKeyDown(KeyCode.Mouse0))
Transform n = (Transform)Instantiate(Q,transform.position,transform.rotation);
Vector3 f = transform.TransformDirection(Vector3.forward);
n.rigidbody.AddForce(f*2000);
print(x+"--"+z);
public Transform Q;
建立一个炮弹 Q&&
Inherits from ,IEnumerable
Position, rotation and scale of an object.
物体的位置、旋转和缩放。
Every object in a scene has a Transform. It's used to store and manipulate the position, rotation and scale of the object. Every Transform can have a parent, which allows you to apply position, rotation and scale hierarchically. This is the hierarchy seen in the Hierarchy pane. They also support enumerators so you can loop through children using:
场景中的每一个物体都有一个Transform。用于储存并操控物体的位置、旋转和缩放。每一个Transform可以有一个父级,允许你分层次应用位置、旋转和缩放。可以在Hierarchy面板查看层次关系。他们也支持计数器(enumerator),因此你可以使用循环遍历子物体。
using UnityE
using System.C
public class example :
public void Awake() {
foreach (Transform child in transform) {
child.position +=
// Moves all transform children 10 units upwards!
//向上移动所有变换的子物体10个单位
for (var child :
in transform) {
child.position +=
参见: 类.
Variables变量
The position of the transform in world space. 在世界空间坐标transform的位置。
Position of the transform relative to the parent transform. 相对于父级的变换的位置。
The rotation as Euler angles in degrees. 旋转作为欧拉角度。
The rotation as Euler angles in degrees relative to the parent transform's rotation. 旋转作为欧拉角度,相对于父级的变换旋转角度。
The red axis of the transform in world space. 在世界空间坐标变换的红色轴。也就是x轴。
The green axis of the transform in world space. 在世界空间坐标变换的绿色轴。也就是y轴。
The blue axis of the transform in world space. 在世界空间坐标变换的蓝色轴。也就是z轴。
The rotation of the transform in world space stored as a Quaternion. 在世界空间坐标物体变换的旋转角度作为储存。
The rotation of the transform relative to the parent transform's rotation. 物体变换的旋转角度相对于父级的物体变换的旋转角度。
The scale of the transform relative to the parent. 相对于父级物体变换的缩放。
The parent of the transform. 物体变换的父级。
Matrix that transforms a point from world space into local space (Read Only). 矩阵变换的点从世界坐标转为自身坐标(只读)。
Matrix that transforms a point from local space into world space (Read Only). 矩阵变换的点从自身坐标转为世界坐标(只读)。
Returns the topmost transform in the hierarchy. 返回层次最高的变换。
The number of children the Transform has. 变换的子物体数量。
The global scale of the object (Read Only). 物体的全局缩放(只读)。
Functions函数
Moves the transform in the direction and distance of translation. 移动transform在translation的方向和距离。
Applies a rotation of eulerAngles.z degrees around the z axis, eulerAngles.x degrees around the x axis, and eulerAngles.y degrees around the y axis (in that order). 应用一个欧拉角的旋转角度,eulerAngles.z度围绕z轴,eulerAngles.x度围绕x轴,eulerAngles.y度围绕y轴(这样的顺序)。
Rotates the transform about axis passing through point in world coordinates by angle degrees. 按照angle度通过在世界坐标的point轴旋转物体。
Rotates the transform so the forward vector points at /target/'s current position. 旋转物体,这样向前向量指向target的当前位置。
Transforms direction from local space to world space. 从自身坐标到世界坐标变换方向。
Transforms a direction from world space to local space. The opposite of Transform.TransformDirection. 变换方向从世界坐标到自身坐标。和相反。
Transforms position from local space to world space. 变换位置从自身坐标到世界坐标。
Transforms position from world space to local space. The opposite of Transform.TransformPoint. 变换位置从世界坐标到自身坐标。和相反。
Unparents all children. 所有子物体解除父子关系。
Finds a child by name and returns it. 通过名字查找子物体并返回它。
Is this transform a child of parent? 这个变换是父级的子物体?
Inherited members继承成员
Inherited Variables继承变量
attached to this
(null if there is none attached). 附加到(游戏物体)(如无附加则为空)。
attached to this
(null if there is none attached). 附加到(游戏物体)(如无附加则为空)。
attached to this
(null if there is none attached). 附加到(游戏物体)(如无附加则为空)。
attached to this
(null if there is none attached). 附加到(游戏物体)(如无附加则为空)。
attached to this
(null if there is none attached). 附加到(游戏物体)(如无附加则为空)。
attached to this
(null if there is none attached). 附加到(游戏物体)(如无附加则为空)。
attached to this
(null if there is none attached). 附加到(游戏物体)(如无附加则为空)。
attached to this
(null if there is none attached). 附加到(游戏物体)(如无附加则为空)。
attached to this
(null if there is none attached). 附加到(游戏物体)(如无附加则为空)。
attached to this
(Read Only). (null if there is none attached) 附加到(游戏物体)(只读)(如无附加则为空)。
attached to this
(Read Only). (null if there is none attached) 附加到(游戏物体)(只读)(如无附加则为空)。
attached to this
(null if there is none attached). 附加到(游戏物体)(如无附加则为空)。
attached to this
(null if there is none attached). 附加到(游戏物体)(如无附加则为空)。
attached to this
(null if there is none attached). 附加到(游戏物体)(如无附加则为空)。
The game object this component is attached to. A component is always attached to a game object. 组件附加的游戏物体。一个组件总是被附加到一个游戏物体。
The tag of this game object. 游戏物体的标签。
The name of the object. //物体的名字
Should the object be hidden, saved with the scene or modifiable by the user? 物体是否被隐藏、保存在场景中或被用户修改?
Inherited Functions继承函数
Returns the component of Type type if the game object has one attached, null if it doesn't. 如果游戏物体有一个附加,则返回Type类型的组件,如果没有则为null。
Returns the component with name type if the game object has one attached, null if it doesn't. 如果游戏物体有一个附加,则返回名字类型组件,如果没有则为null。
Returns the component of Type type in the
or any of its children using depth first search. 返回Type类型组件,在或它的任何子物体使用深度优先搜索,仅返回激活的组件。
Returns all components of Type type in the
or any of its children. 在或任何它的子物体,返回全部Type类型组件
Returns all components of Type type in the . 在游戏物体返回全部Type类型组件。
Is this game object tagged tag? 游戏物体有被标记标签么?
Calls the method named methodName on every
in this game object and on every ancestor of the behaviour 在游戏物体每一个和每一个behaviour的祖先上调用名为methodName的方法。
Calls the method named methodName on every
in this game object. 在游戏物体每一个上调用名为methodName的方法。
Calls the method named methodName on every
in this game object or any of its children. 在游戏物体每一个和它的全部子物体上调用名为methodName的方法。
Returns the instance id of the object. 返回物体的实例ID
Returns the name of the game object. 返回游戏物体的名称。
Inherited Class Functions继承类函数
Does the object exist? 物体是否存在?
Clones the object original and returns the clone. 克隆原始物体,并返回克隆的物体
Removes a gameobject, component or asset. 删除一个游戏物体、组件或资源
Destroys the object obj immediately. It is strongly recommended to use Destroy instead. 立即销毁物体obj,强烈建议使用Destroy代替。
Returns a list of all active loaded objects of Type type. 返回Type类型的所有激活的加载的物体列表
Returns the first active loaded object of Type type. 返回Type类型第一个激活的加载的物体。
Compares if two objects refer to the same 比较如果两个物体相同
Compares if two objects refer to a different object 比较如果两个物体不同
Makes the object target not be destroyed automatically when loading a new scene. 加载新场景的时候使目标物体不被自动销毁。
int speed=50;
if(Input.GetKeyDown(KeyCode.Mouse0))
按下鼠标左键
Transform n = (Transform)Instantiate(Q,transform.position,transform.rotation);
创建一个新炮弹
Instantiate 是object类型& 需要强制转换
Vector3 f = transform.TransformDirection(Vector3.forward);
三维坐标 Vector3.forward 0 0 1 向前
n.rigidbody.AddForce(f*2000);
给跑断加力
点击 摄像头 把炮弹拖向 定义的public的变量
www.520books.com
阅读(...) 评论()unity中如何让炮塔自动攻击一定范围内的目标,这个你是怎么做到的啊??_百度知道
unity中如何让炮塔自动攻击一定范围内的目标,这个你是怎么做到的啊??
我有更好的答案
声明一个GameObejct列表作为目标列表给炮塔加一个空对象作为子物体然后为其添加触发器,判断是否有物体在触发器内停留若有则由炮塔向物体发射射线判断是否有其他物体阻挡,若没有则将该物体加入目标列表
有代码可以给我看看吗??
采纳率:84%
为您推荐:
其他类似问题
unity的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。Unity3D 学习教程 13 C# 销毁炮弹gameObject.renderer.enabled //是控制一个物体是否在屏幕上渲染或显示 而物体实际还是存在的 只是想当于隐身 而物体本身的碰撞体还依然存在的GameObject.Destroy() //表示移除物体或物体上的 代表销毁该物体 实际上该物体的内存并没有立即释放 而是在你下下个场景中槽释放内存资源,就是你a场景中Destroy了 一般是在c场景中才真正释放该物体的内存资源(这是我的体会 不知道理解错误没)gameObject.active //是否在场景中停用该物体 在你gameObject.active =false中 则你在场景中用find找不到该物体 //如果该物体有子物体 你要用SetActiveRecursively(false) 来控制是否在场景中停用该物体(递归的)我们要介绍是销毁物体Destroy() 1 using UnityE 2 using System.C 3
4 public class acc : MonoBehaviour { 5
// Use this for initialization 7
public Transform Q; 8
int speed=50; 9
void Start () {10 11
// Update is called once per frame14
void Update () {15
float x = Input.GetAxis("Horizontal") * Time.deltaTime *//左右移动16
float z = Input.GetAxis("Vertical") * Time.deltaTime *//
前后移动17
//主摄像机物体
transform.Translate(x,0,z);19 20
if(Input.GetKeyDown(KeyCode.Mouse0))21
//实列化子弹24
Transform n = Instantiate(Q) as T25
//发射子弹的位置为物体的位置26
n.position = transform.27
Vector3 f = transform.TransformDirection(Vector3.forward);29
n.gameObject.rigidbody.AddForce(f*3000);30
Destroy(n.gameObject,5);31
//Destroy(n.gameObject);32
//Destroy(gameObject);33
}37 }5秒后 销毁物体Destroy(n.gameObject,5);立即销毁物体Destroy(n.gameObject);如果文件绑定在物体上用Destroy(gameObject);来销毁物体Unity资源内存申请和释放1.资源类型GameObject, Transform, Mesh, Texture, Material, Shader, Scrt和各种其他Assets。2.资源创建方式静态引用,在脚本中加一个public GameObject变量,在Inspector面板中拖一个efab到该变量上,然后在需要引用的地方Instantiate;Resource.Load,资源需要放在Assets/Resources目录下;AssetBundle.Load, Load之后Instantiate。3. 资源销毁方式GameObject.Destroy(gameObject),销毁该物体;AssetBundle.Unload(false),释放AssetBundle文件内存镜像,不销毁Load创建的Assets对象;AssetBundle.Unload(true),释放AssetBundle文件内存镜像同时销毁所有已经Load的Assets内存镜像;Resources.UnloadAsset(Object),释放已加载的Asset对象;Resources.UnloadUnusedAssets,释放所有没有引用的Asset对象。4. 生命周期实验篇实验中创建了一个简单场景,场景中创建了一个Empty GameObject,上面挂了一个脚本,在Awake函数中通过协程函数来创建资源,具体的Coroutine函数下面都有。 实验中创建的Prefab是一个坦克车,加入场景中场景内存增加3M左右,同时创建了一个AssetBundle资源供AssetBundle使用。1. Resources.Load方式加载一个Prefab, 然后Instantiate GameObject代码如下:
IEnumerator LoadResources()
// 清除干净以免影响测试结果
Resources.UnloadUnusedAssets();
// 等待5秒以看到效果
yield return new WaitForSeconds(5.0f);
// 通过Resources.Load加载一个资源
GameObject tank = Resources.Load("Role/Tank") as GameO
yield return new WaitForSeconds(0.5f);
// Instantiate一个资源出来
GameObject tankInst = GameObject.Instantiate(tank, Vector3.zero, Quaternion.identity) as GameO
yield return new WaitForSeconds(0.5f);
// Destroy一个资源
GameObject.Destroy(tankInst);
yield return new WaitForSeconds(0.5f);
//释放无用资源
Resources.UnloadUnusedAssets();
yield return new WaitForSeconds(0.5f);
}执行结果如下:下面是统计结果:数据描述MemoryTextureMeshMaterialGameObjectsObjects in SceneTotal Objects初始72.8MM35/223.0K<td style="padding: 8 line-height: 20 vertical-align: border-top-color: # border-left-color: # border-top-width: 1 border-left-width: 1 border-top-style: borde
优质网站模板Unity教程 | 从零开始制作一款3D炸弹超人游戏
说起炸弹超人,相信很多朋友都玩过类似的游戏,其中最为人熟知的莫过于《泡泡堂》。该类型游戏需要玩家在地图中一边跑动一边放置炸弹,同时还要躲避敌方炸弹保护自己。最初的炸弹超人游戏都是2D的,今天这篇文章将教大家在Unity中实现一款3D的炸弹超人游戏。
温馨提示,本教程需要大家了解Unity的基本操作与脚本概念。请点击【阅读原文】进入Unity官方中文社区(unitychina.cn),下载初始项目资源。
将项目初始资源导入Unity项目,资源目录如下:
其中分别包含要用于游戏的动画、材质、模型、背景音乐、物理材质、预制件、场景、脚本、音效及图片资源。
打开项目中的Game场景并运行。
可以通过WASD键或方向键来操作所有角色进行移动。下面来让角色可以放置炸弹。角色1(红色)通过按下空格键来放置炸弹,角色2(蓝色)则通过按下回车键进行同样的操作。
打开Player脚本,该脚本负责角色所有的移动及动画逻辑。找到DropBomb函数,添加代码如下:
其中RoundToInt函数用于对炸弹的坐标参数四舍五入,以避免炸弹放置位置偏离出地块中心。
运行场景,效果如下:
创建爆炸效果
在s文件夹下新建C#脚本命名为Bomb:
找到Prefabs文件夹下的Bomb预制件,将Bomb脚本绑定到该游戏对象上。然后打开Bomb脚本,添加代码如下:
在检视面板中,将Bomb预制件赋值给脚本的Explosion Prefab属性,该属性用于定义需要生成爆炸效果的对象。Bomb脚本使用了协程来实现爆炸的效果,StartCoroutine函数将朝着4个方向调用CreateExplosions函数,该函数用于生成爆炸效果,在For循环内遍历炸弹能够炸到的所有单元,然后为能够被炸弹影响的各个单元生成爆炸特效,炸弹对墙壁是没有伤害的。最后,在进入下一次循环前等待0.05秒。
代码作用类似下图:
红线就是Raycast,它会检测炸弹周围的单元是否为空,如果是,则朝着该方向生成爆炸效果。如果碰撞到墙,则不生成爆炸并停止检测该方向。所以前面需要让炸弹在地块中心生成,否则就会出现不太理想的效果:
Bomb代码中定义的LayerMask用于剔除射线对地块的检测,这里还需要在检视面板中编辑层,并新增用户层命名为“Blocks”,然后将层级视图中Blocks游戏对象的Layer设置为“Blocks”。
更改Blocks对象的层级时会跳出提示框,询问是否更改子节点,选择是即可:
然后选中Bomb对象,在检视面板中将Bomb脚本的Level Mask设为“Blocks”:
如果炸弹炸到了另一个炸弹,那么被炸到的炸弹也会爆炸。Bomb脚本中的OnTriggerEnter函数是MonoBehaviour预定义的函数,会在触发器与Rigidbody碰撞之前调用。这里OnTriggerEnter会检测被碰撞的炸弹是否是被炸弹特效所碰撞,如果是,则该炸弹也要爆炸。
现在运行场景,效果如下:
判定游戏结果
打开Player脚本,添加下面的代码:
其中GlobalManager是GlobalStateManager脚本的引用,该脚本用于通知玩家获胜或死亡的消息。dead则用于标志玩家是否死亡。
更改OnTriggerEnter函数代码如下:
该函数作用为设置dead变量来通知玩家死亡,并告知全局状态管理器玩家的死亡信息,然后销毁玩家对象。
在检视面板中选中两个玩家对象,将Global State Manager游戏对象赋值给Player脚本的Global Manger字段。
再次运行场景,效果如下:
打开GlobalStateManager脚本,添加以下代码:
其中deadPlayers表示死亡的玩家数量,deadPlayerNumber则用于记录死亡玩家的编号。PlayerDied函数用于添加死亡玩家,并设置deadPlayerNumber属性,在0.3秒后检测另一位玩家是否也死亡。
然后在脚本中添加CheckPlayersDeath函数,代码如下:
以上代码用于判断哪位玩家获得胜利,如果两位玩家均死亡,则打成平局。
运行场景,效果如下:
到此本篇教程就结束了,大家还可以在此基础上对该项目进行扩展,例如添加“推箱子”功能,将位于自己脚边的炸弹推给敌方,或是限制能够放置的炸弹数量,添加快速重新开始游戏的界面,设置可以被炸弹炸毁的障碍物,设置一些道具用于获得炸弹或者增加生命值,还可以增加多人对战模式与朋友一起变身炸弹超人等等。大家都来发挥自己的创意吧!
进入Unity官方中文社区(unitychina.cn),可下载示例工程并查看所有代码!
更多Unity相关技术文章
Unity官方活动
,学习使用Unity做一款小游戏,还有机会赢得Unity限量大礼哦!
责任编辑:
声明:该文观点仅代表作者本人,搜狐号系信息发布平台,搜狐仅提供信息存储空间服务。
今日搜狐热点51CTO旗下网站
如何使用Unity3D+C#开发炸弹人游戏
炸弹人游戏是上世纪80年代广泛流行的一个2D游戏,本文介绍如何使用Unity3D创建像炸弹人这样的基本类型的游戏,包括一些粒子系统用于炸弹与爆炸效果。
作者:朱先忠编译来源:| 10:27
炸弹人游戏是上世纪80年代广泛流行的一个2D游戏,本文创建的是一个基本型的此游戏的Unity3D版本。
通过本游戏,你可以实现如下功能:
投掷炸弹并把它放到特定位置
通过光线跟踪技术激活炸弹
处理与玩家的爆炸碰撞
处理与炸弹的爆炸碰撞
游戏结局处理
首先,请下载一个我为本文游戏建立的,然后把它放到一个你指定的位置。
然后,使用Unity3D打开这个项目,注意到Assets文件夹下包含了好多的子文件夹,如图所示。
这里具体说一下各个文件夹的主要功能:
Animation Controllers:存储着游戏控制器部分,包括的逻辑部分。
Materials:包含构建各关卡场景所需要的块(Block)材质。
Models:存储玩家、关卡及炸弹模型,及其相关材质。
Music:存储游戏的音效文件。
Materials:存储玩家的物理材质数据,它们是一些特殊类型的材质,用于实现特定的物理属性。在本教程中,用于使玩家在无摩擦情况下轻松地在关卡中穿越。
Prefabs:包含炸弹及爆炸的预制数据。
Scenes:对应于游戏场景数据。
Scripts:包含游戏的启动脚本,其中添加的大量注释将有利于读者阅读源码。
Sound Effects:包含炸弹及爆炸效果相关的声效文件。
Textures:包含两个玩家的纹理数据。
如果你还没有打开游戏工程,请抓紧打开,然后试着运行一下此程序。没有其他问题的话,你会观察到如图所示的情形:
你会注意到,游戏中的两个玩家可以通过键盘上的WASD四个字符键或者四个箭头键驱动,使其沿着游戏地图运动。
通常,当按下空格键时红色玩家会在其脚下安置一枚炸弹,而另一个玩家也能够做同样的事情&&只是通过按回车键实现。
然而,目前我们还没有实现这一功能。为此,你需要先编写放置炸弹的代码。现在,请你使用自己喜欢的代码编辑器打开脚本文件Player.cs。
此脚本负责处理所有的玩家运动及动画逻辑,还包含一个方法DropBomb,当关联游戏对象(GameObject)bombPrefab时,它用于检测目的。
private&void&DropBomb()&{&if&(bombPrefab)&{&//Check&if&bomb&prefab&is&assigned&first&}&}&
为了实现一个炸弹掉落在玩家下面的效果,在if语句中添加下面的代码:
Instantiate(bombPrefab,&myTransform.position,&bombPrefab.transform.rotation);&
上述代码将在玩家脚下生成炸弹(随着玩家的运动路径的变化,将生成成串的炸弹)。现在,运行一下游戏工程,你会观察到如下图所示效果:
目前,效果不错吧!
但是,还有一个小问题:炸弹投掷的方式如何?如果是无论在哪里你都能放炸弹的话,当你需要计算爆炸应该发生的位置时就会带来一些问题。
接下来,本教程将向你具体介绍如何实现爆炸的所有细节。
下一步任务是确保炸弹在丢掉时能够附着到相应位置,从而实现炸弹很好地与地板上的网格对齐。由于我们的设计中网格上的每个图块大小是 1 &
1,所以进行此更改是相当容易的。
打开文件Player.cs,编辑一下Instantiate()函数,像下面这样:
Instantiate(bombPrefab,&new&Vector3(Mathf.RoundToInt(myTransform.position.x),&bombPrefab.transform.position.y,&Mathf.RoundToInt(myTransform.position.z)),&bombPrefab.transform.rotation);&
注意,这里函数Mathf.RoundToInt调用中使用了玩家位置的x和z两个参数值,每一个浮点类型值被转换为一个整型值,这就可以实现炸弹很好地与地板上的网格对齐的效果:
现在,你可以再次启动工程来运行一下,你会观察到当投掷炸弹时,这些炸弹恰好能够对齐网格:
虽然把炸弹投掷到地图上是很有趣的,但你知道真正有趣的事是如何实现爆炸!为此,我们再来添加一些功能。
创建爆炸效果
首先,我们要创建一个新的脚本文件:
(1)从Project视图下选择Scripts文件夹;
(2)按下Create按钮;
(3)选择&C# Script&;
(4)把脚本文件命名为Bomb即可。
现在,把Bomb.cs脚本关联到预制Bomb上:
(1)在Prefabs文件夹中选择GameObject Bomb;
(2)点击按钮&Add Component&;
(3)在搜索框中输入&bomb&;
(4)选择你刚刚创建的脚本Bomb.cs;
(5)打开此脚本文件,然后在其Start()方法中输入如下代码:
Invoke(&Explode&,&3f);&
此方法使用了两个参数,第一个是将要调用的方法名称,第二个是在调用此方法时需要延迟的时间数。在本例中,想实现炸弹在3秒内爆炸的效果。我们将在后面添加这个Explode方法的具体内容。
现在,只是在Update()方法下面添加这个方法占位符形式(目前为空):
void&Explode()&{&}&
在生成任何GameObject
Explosion之前,还需要创建一个公共类型的GameObjet对象,以便进行预制Explosion的赋值。恰好在Start()方法上面定义如下代码:
public&GameObjectexplosionP&
保存此文件,然后从Prefabs文件夹下选择预制Bomb,然后把预制Explosion拖动到&Explosion Prefab&选项后面空白处。
完成这一操作后,返回到编辑器中。现在开始编写更有意思的代码。
在方法Explode()中,添加如下代码行:
Instantiate(explosionPrefab,&transform.position,&Quaternion.identity);&//1&GetComponent&MeshRenderer&().enabled&=&false;&//2&transform.FindChild(&Collider&).gameObject.SetActive(false);&//3&Destroy(gameObject,&.3f);&//4&
上述代码实现如下功能:
1.在炸弹位置触发爆炸;
2.禁用网络渲染器(mesh render),使炸弹不可见;
3.禁用碰撞器,从而允许玩家在爆炸中移动与行走;
4.在0.3秒后拆除炸弹;这可以确保在删除GameObject之前所有爆炸都会触发。
现在,保存脚本Bomb.cs,返回到编辑器尝试再玩一下游戏。放下一些炸弹并观察一下它们爆炸时良好的效果,参考下图。
设置爆炸音效
为了创建理想的爆炸效果,你需要创建一个协程。
「补充」协程本质上是一个函数,允许你暂停执行并将控制返回到Unity3D。在以后的某个时间点处该函数将从上次离开的位置恢复执行。
人们经常混淆协程与多线程。其实,它们是不同的:协程运行在同一个线程中,并能够在某中间点处及时恢复执行。若要了解更多的关于协程及其定义相关信息,请查阅相关的Unity文档(http://docs.unity3d.com/Manual/Coroutines.html)。
现在,返回到代码编辑器中修改脚本Bomb.cs,在函数Explode()下面添加一个名字为CreateExplosions的IEnumberator:
private&IEnumeratorCreateExplosions(Vector3&direction)&{&return&null&//&placeholder&for&now&}&
现在,请把下面四行代码添加到函数Explode()内部的Instantiate调用与MeshRender禁用之间:
StartCoroutine(CreateExplosions(Vector3.forward));&StartCoroutine(CreateExplosions(Vector3.right));&StartCoroutine(CreateExplosions(Vector3.back));&StartCoroutine(CreateExplosions(Vector3.left));&
这里的StartCoroutine调用将针对游戏场景中的每个方向触发CreateExplosions。
现在,更有趣的时刻到了。在方法CreateExplosions()内部加入如下代码:
//1&for&(inti&=&1;&i&&3;&i++)&{&&//2&RaycastHit&&&//3&Physics.Raycast(transform.position&+&new&Vector3(0,.5f,0),&direction,&out&hit,&i,&levelMask);&&//4&if&(!hit.collider)&{&Instantiate(explosionPrefab,&transform.position&+&(i&*&direction),&&//5&explosionPrefab.transform.rotation);&&//6&}&else&{&&//7&&}&&//8&yield&return&new&WaitForSeconds(.05f);&}&
这段代码看起来相当复杂,但实际上相当简单。详细解释如下:
1.通过for循环来遍历你想要爆炸覆盖的每个单位距离。在本例情况下,爆炸将达到两米的距离。
2.RaycastHit对象包含有关Raycast击中的是什么对象及击中位置的所有信息,当然也可能没有击中。
3.上述代码中非常重要的代码行是StartCoroutine调用,这个调用中实现从炸弹中心朝你通过的方向发出raycast。然后,它将结果输出到RaycastHit对象。I
参数指示射线走过的距离。最后,代码中使用命名为levelMask的层蒙版(LayerMask)来确保射线只检查当前关卡中的块而忽略检查玩家及其他的碰撞对象。
4.如果raycast没有撞到任何东西,那么说明这个块(Block)是一个自由块。
5.在raycast检查的位置产生爆炸。
6.Raycast击中块。
7.一旦raycast击中一个块,它就跳出for循环。这将确保爆炸不会跨越墙。
8.在进行下一个for循环迭代前等待0.05秒。这将使爆炸呈现向外扩展的效果而更具有说服力。
下图给出的是上面添加代码后的动画效果:
注意,下图中的红线是raycast。它围绕炸弹检查一段自由空间距离;如果发现存在碰撞,那么将产生爆炸。当它击中块时,它并不产生任何东西并停止在那个方向上的检查。
现在,你该明白了为什么炸弹需要附着到网格中各小格子中心了吧。如果炸弹能去任何地方,那么在一些边缘情况下,raycast会击中块却并不产生任何爆炸,因为它没有正确地进行水平对齐。
添加遮罩层
在Bomb代码中还存在一个错误:事实上LayerMask并不存在。因此,现在就在explosionPrefab变量声明的下面,再添加一行代码,如下:
public&GameObjectexplosionP&public&LayerMasklevelM&
LayerMask通常使用raycasts技术有选择地筛选出特定图层。在本例情况下,你只需要筛选出块部分,所以,raycasts技术并没有做什么事。
保存Bomb脚本并返回到Unity编辑器。单击右上角的Layers按钮并选择Edit Layers...
现在,请点击User Layer 8旁边的文本框并输入&Blocks&。这样就定义了你可以使用的新层。
在层次视图中,选择GameObject Blocks,如下图所示:
把图层改变为你刚刚创建的图层Blocks,如下图所示:
当出现&Change Layer&对话框时点击&Yes,change children&按钮,以便应用于地图上所有散布的黄色长方体块。
最后,从Prefabs文件夹下选择预制Bomb,并把遮罩层改成Blocks。
现在,再次运行一下游戏场景并投掷几枚炸弹。你会观察到爆炸效果比以前好多了:良好地分布于各长方体块之间!
恭喜你,你已经攻克了本游戏中最困难的编码部分。剩下的是为游戏添加一些附加效果。
当一枚炸弹爆炸时会接触到另一个炸弹,这枚相邻的炸弹也应该爆炸,这将产生一种更令人惊喜的效果。
值得欣喜的是,上述效果并不难实现。
现在打开脚本文件Bomb.cs,然后在方法CreateExplosions()下面添加一个新的方法OnTriggerEnter:
public&void&OnTriggerEnter(Collider&other)&{&}&
OnTriggerEnter方法是MonoBehaviour中一个预定义的方法,在触发器碰撞器与刚体碰撞时激活执行。碰撞器参数是other,对应于进入触发器的游戏物体(GameObject)的碰撞器。
在本例情况下,你需要检查碰撞对象,并确定当该对象是一个爆炸对象时使之爆炸。
首先,你需要知道是否发生炸弹爆炸。需要首先声明exploded变量,因此在levelMask变量声明下面添加以下声明:
private&bool&exploded&=&false;&
然后,在方法OnTriggerEnter()内部添加如下代码:
if&(!exploded&&other.CompareTag(&Explosion&))&{&//&1&&&2&CancelInvoke(&Explode&);&//&2&Explode();&//&3&}&
这段代码做了三件事情:
1.检查炸弹是否已经爆炸了;
2.检查触发器碰撞器是否已经有标签Explosion;
3.通过投掷炸弹取消已经调用的Explode调用&&如果不这样做,炸弹可能会爆炸两次;
4.实现爆炸。
现在你已经定义了变量,但是还没有作任何修改。而最合乎逻辑的地方是在Explode()函数中实现这一操作(应当在禁用组件MeshRenderer之后),代码如下:
...&GetComponent&MeshRenderer&().enabled&=&false;&exploded&=&true;&...&
现在准备好了一切,请保存一下刚才的文件修改,然后再次运行一下工程。再次投掷一枚炸弹,并连续在其周围投掷炸弹,观察效果:
最后剩下的事情是处理玩家对于爆炸的反应情况,以及游戏结局处理逻辑。
游戏结局处理
打开文件Player.cs。目前还没有定义变量来表示玩家的死活;因此,在脚本顶部添加一个布尔变量,如下所示:
public&cool&dead=false;&
这个变量用于跟踪是否玩家在爆炸以后死亡。
接下来,在其他变量声明后面添加如下变量声明:
public&GlobalStateManagerGlobalM&
注意,到现在在方法OnTriggerEnter()内部已经能够检查是否玩家被炸弹击中,但目前实现的仅仅是通过控制台窗口输出这一消息。因此,现在请将如下代码添加到Debug.Log调用后面:
dead&=&true;&//&1&GlobalManager.PlayerDied(playerNumber);&//&2&Destroy(gameObject);&//&3&
这段代码实现如下功能:
1.修改变量dead,以便跟踪玩家死亡的消息;
2.通知全局状态管理器玩家已经死亡;
3. 销毁玩家对象GameObject。
现在,保存一下文件并返回到Unity编辑器中。你需要把GlobalStateManager连接到两个玩家:
(1)在层次窗口内,选择两个Player GameObject。
(2)把全局状态管理器GameObject拖动到它们的Global Manager选项处。
再次运行游戏场景,确保至少有一个玩家被炸弹击中,参考下图。
每一个遭遇到爆炸的玩家都会立即死亡。
但是,目前为止游戏并不知道谁赢了,因为GlobalStateManager还没有使用它收到的信息。下面来讨论这件事情。
打开文件GlobalStateManager.cs。为了使GlobalStateManager能够跟踪玩家的死亡,还需要定义两个变量。在函数PlayerDied()上面加上下面的定义:
private&intdeadPlayers&=&0;&private&intdeadPlayerNumber&=&-1;&
首先,变量deadPlayers会存储死亡的玩家数量。一旦第一个玩家死亡,变量deadPlayerNumber即被修改,此变量也表示了是哪一位玩家这种额外信息。
准备好了上面变量后,现在加入实际逻辑。在函数PlayerDied()中加入如下代码:
deadPlayers++;&//&1&if&(deadPlayers&==&1)&{&//&2&deadPlayerNumber&=&playerN&//&3&Invoke(&CheckPlayersDeath&,&.3f);&//&4&}&
这段代码的功能是:
1.添加一个死亡玩家;
2.进一步判断是否这是第一个死亡玩家&
3.把死亡玩家数设置为首先死亡的玩家;
4.检查是否另一个玩家也死亡了,还是在0.3秒后仅起了一些爆炸尘埃而没有死亡。
最后的一点时间延迟对于绘制检查来说很重要。如果立即进行检查,你可能发现不了有人死亡,而0.3秒对于判断是否每一个人都死亡了已经足够了。
现在,请在GlobalStateManager脚本中添加一个新方法CheckPlayersDeath:
void&CheckPlayersDeath()&{&//&1&if&(deadPlayers&==&1)&{&//&2&if&(deadPlayerNumber&==&1)&{&Debug.Log(&Player&2&is&the&winner!&);&//&3&}&else&{&Debug.Log(&Player&1&is&the&winner!&);&}&//&4&}&else&{&Debug.Log(&The&game&ended&in&a&draw!&);&}&}&
上述条件语句的功能列举如下:
1.只有一个玩家死亡,则判定他是输家;
2.玩家1死亡了,那么玩家2是赢家;
3.玩家2死亡了,那么玩家1是赢家;
4.两个玩家都死亡了,那么这是一场平局。
现在,再保存并运行一下你的工程试试吧,参考下图:
请并进行详细研究吧!
你通过本文了解了如何使用Unity3D创建像炸弹人这样的基本类型的游戏。
本文使用了一些粒子系统用于炸弹与爆炸效果。更多的有关信息,请参考。
最后,强烈建议你做如下增强性修改:
(1)可以使炸弹能够被推动,这样当炸弹靠近你时你可以逃跑,而把炸弹推到你的对手身上;
(2)限制可以投掷的炸弹数量;
(3)加入重新启动游戏功能;
(4)伴随爆炸加入可破裂的场景中的块(Blocks);
(5)你可以增加一些有趣的装备;
(6)多加几条命,以及使用某种方式来进行购买;
(7)创建漂亮的UI元素来显示玩家赢了什么东西;
(8)探讨某种方法来添加更多的玩家,等等。
【编辑推荐】
【责任编辑: TEL:(010)】
大家都在看猜你喜欢
头条热点热点热点热点
24H热文一周话题本月最赞
讲师:96311人学习过
讲师:51257人学习过
讲师:112105人学习过
精选博文论坛热帖下载排行
本书由浅入深、循序渐进地介绍了目前流行的基于Eclipse的优秀框架。全书共分14章,内容涵盖了Eclipse基础、ANT资源构造、数据库应用开发、W...
订阅51CTO邮刊

我要回帖

更多关于 unity3d游戏制作 的文章

 

随机推荐