说起炸弹超人,相信很多朋友都玩过类似的游戏,其中最为人熟知的莫过于《泡泡堂》。该类型游戏需要玩家在地图中一边跑动一边放置炸弹,同时还要躲避敌方炸弹保护自己。最初的炸弹超人游戏都是2D的,今天这篇文章将教大家在Unity中实现一款3D的炸弹超人游戏。

准备工作

将项目初始资源导入Unity项目,资源目录如下:

其中分别包含要用于游戏的动画、材质、模型、背景音乐、物理材质、预制件、场景、脚本、音效及图片资源。

放置炸弹

打开项目中的Game场景并运行。

可以通过WASD键或方向键来操作所有角色进行移动。下面来让角色可以放置炸弹。角色1(红色)通过按下空格键来放置炸弹,角色2(蓝色)则通过按下回车键进行同样的操作。

打开Player脚本,该脚本负责角色所有的移动及动画逻辑。找到DropBomb函数,添加代码如下:

 /// <summary>
/// Drops a bomb beneath the player
/// </summary>
private void DropBomb() {
if (bombPrefab) { //Check if bomb prefab is assigned first
// Create new bomb and snap it to a tile
Instantiate(bombPrefab,
new Vector3(Mathf.RoundToInt(myTransform.position.x), bombPrefab.transform.position.y, Mathf.RoundToInt(myTransform.position.z)),
bombPrefab.transform.rotation);
}
}

其中RoundToInt函数用于对炸弹的坐标参数四舍五入,以避免炸弹放置位置偏离出地块中心。

运行场景,效果如下:

创建爆炸效果

在Scripts文件夹下新建C#脚本命名为Bomb:

找到Prefabs文件夹下的Bomb预制件,将Bomb脚本绑定到该游戏对象上。然后打开Bomb脚本,添加代码如下:

 using UnityEngine;
using System.Collections;
using System.Runtime.CompilerServices; public class Bomb : MonoBehaviour {
public AudioClip explosionSound;
public GameObject explosionPrefab;
public LayerMask levelMask; // This LayerMask makes sure the rays cast to check for free spaces only hits the blocks in the level
private bool exploded = false; // Use this for initialization
void Start() {
Invoke("Explode", 3f); //Call Explode in 3 seconds
} void Explode() {
//Explosion sound
AudioSource.PlayClipAtPoint(explosionSound,transform.position); //Create a first explosion at the bomb position
Instantiate(explosionPrefab, transform.position, Quaternion.identity); //For every direction, start a chain of explosions
StartCoroutine(CreateExplosions(Vector3.forward));
StartCoroutine(CreateExplosions(Vector3.right));
StartCoroutine(CreateExplosions(Vector3.back));
StartCoroutine(CreateExplosions(Vector3.left)); GetComponent<MeshRenderer>().enabled = false; //Disable mesh
exploded = true;
transform.FindChild("Collider").gameObject.SetActive(false); //Disable the collider
Destroy(gameObject,.3f); //Destroy the actual bomb in 0.3 seconds, after all coroutines have finished
} public void OnTriggerEnter(Collider other) {
if (!exploded && other.CompareTag("Explosion")) { //If not exploded yet and this bomb is hit by an explosion...
CancelInvoke("Explode"); //Cancel the already called Explode, else the bomb might explode twice
Explode(); //Finally, explode!
}
} private IEnumerator CreateExplosions(Vector3 direction) {
for (int i = ; i < ; i++) { //The 3 here dictates how far the raycasts will check, in this case 3 tiles far
RaycastHit hit; //Holds all information about what the raycast hits Physics.Raycast(transform.position + new Vector3(,.5f,), direction, out hit, i, levelMask); //Raycast in the specified direction at i distance, because of the layer mask it'll only hit blocks, not players or bombs if (!hit.collider) { // Free space, make a new explosion
Instantiate(explosionPrefab, transform.position + (i * direction), explosionPrefab.transform.rotation);
}
else { //Hit a block, stop spawning in this direction
break;
} yield return new WaitForSeconds(.05f); //Wait 50 milliseconds before checking the next location
} }
}

在检视面板中,将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脚本,添加下面的代码:

 //Manager
public GlobalStateManager GlobalManager; //Player parameters
[Range(, )] //Enables a nifty slider in the editor
public int playerNumber = ; //Indicates what player this is: P1 or P2
public float moveSpeed = 5f;
public bool canDropBombs = true; //Can the player drop bombs?
public bool canMove = true; //Can the player move?
public bool dead = false; //Is this player dead?

其中GlobalManager是GlobalStateManager脚本的引用,该脚本用于通知玩家获胜或死亡的消息。dead则用于标志玩家是否死亡。

更改OnTriggerEnter函数代码如下:

 public void OnTriggerEnter(Collider other) {
if (!dead && other.CompareTag("Explosion")) { //Not dead & hit by explosion
Debug.Log("P" + playerNumber + " hit by explosion!"); dead = true;
GlobalManager.PlayerDied(playerNumber); //Notify global state manager that this player died
Destroy(gameObject);
}
}

该函数作用为设置dead变量来通知玩家死亡,并告知全局状态管理器玩家的死亡信息,然后销毁玩家对象。

在检视面板中选中两个玩家对象,将Global State Manager游戏对象赋值给Player脚本的Global Manger字段。

再次运行场景,效果如下:

打开GlobalStateManager脚本,添加以下代码:

 public List<GameObject> Players = new List<GameObject>();

  private int deadPlayers = ;
private int deadPlayerNumber = -; public void PlayerDied(int playerNumber) {
deadPlayers++; if (deadPlayers == ) {
deadPlayerNumber = playerNumber;
Invoke("CheckPlayersDeath", .3f);
}
}

以上代码用于判断哪位玩家获得胜利,如果两位玩家均死亡,则打成平局。

运行场景,效果如下:

总结

到此本篇教程就结束了,大家还可以在此基础上对该项目进行扩展,例如添加“推箱子”功能,将位于自己脚边的炸弹推给敌方,或是限制能够放置的炸弹数量,添加快速重新开始游戏的界面,设置可以被炸弹炸毁的障碍物,设置一些道具用于获得炸弹或者增加生命值,还可以增加多人对战模式与朋友一起变身炸弹超人等等。大家都来发挥自己的创意吧!

文章来自:http://forum.china.unity3d.com/thread-24404-1-1.html

原文链接:https://www.raywenderlich.com/125559/make-game-like-bomberman
原作者:Eric Van de Kerckhove

制作一款3D炸弹超人游戏的更多相关文章

  1. 如何制作一款HTML5 RPG游戏引擎——第五篇,人物&人物特效

    上一次,我们实现了对话类,今天就来做一个游戏中必不可少的——人物类. 当然,你完全是可以自己写一个人物类,但是为了方便起见,还是决定把人物类封装到这个引擎里. 为了使这个类更有意义,我还给人物类加了几 ...

  2. 如何制作一款HTML5 RPG游戏引擎——第四篇,情景对话

    今天我们来实现情景对话.这是一个重要的功能,没有它,游戏将变得索然无味.所以我们不得不来完成它. 但是要知道,使用对话可不是一件简单的事,因为它内部的东西很多,比如说人物头像,人物名称,对话内容... ...

  3. 如何制作一款HTML5 RPG游戏引擎——第三篇,利用幕布切换场景

    开言: 在RPG游戏中,如果有地图切换的地方,通常就会使用幕布效果.所谓的幕布其实就是将两个矩形合拢,直到把屏幕遮住,然后再展开直到两个矩形全部移出屏幕. 为了大家做游戏方便,于是我给这个引擎加了这么 ...

  4. 如何制作一款HTML5 RPG游戏引擎——第二篇,烟雨+飞雪效果

    今天我们来实现烟雨+飞雪效果.首先来说,一款经典的RPG游戏难免需要加入天气的变化.那么为了使我们的RPG游戏引擎更完美,我们就只好慢慢地实现它. 本文为该系列文章的第二篇,如果想了解以前的文章可以看 ...

  5. 用Html5结合Qt制作一款本地化EXE游戏-太空大战(Space War)

    本次来说一说如何利用lufylegend.js引擎制作一款html5游戏后将其通过Qt转换成EXE程序.步骤其实非常简单,接下来就一步步地做一下解释和说明. 首先我们来开发一个有点类似于太空大战的游戏 ...

  6. 如何制作一款HTML5 RPG游戏引擎——第一篇,地图类的实现

    一,话说天下大事 前不久看到lufy的博客上,有一位朋友想要一个RPG游戏引擎,出于兴趣准备动手做一做.由于我研究lufylegend有一段时间了,对它有一定的依赖性,因此就准备将这个引擎基于lufy ...

  7. 3D跑酷游戏《月影忍者之疾风狂逃》

    <月影忍者之疾风狂逃>是一款3D跑酷游戏,也是我实习的时候参与的一个项目,在那个公司我学到了很多东西,谢谢他们.大家可以去玩玩这个游戏啊,还是不错的哦.

  8. 张瀚荣:如何用UE4制作3D动作游戏

    转自:http://www.gamelook.com.cn/2015/06/218267 GameLook报道/ 6月5日,2015年第三期GameLook开放日‧虚幻引擎专场活动在上海正式举行,此次 ...

  9. 基于html5制作3D拳击游戏源码下载

    今天给大家分享一款基于HTML5实现的3d拳王游戏源码.这款实例适用浏览器:360.FireFox.Chrome.Safari.Opera.傲游.搜狗.世界之窗. 不支持IE8及以下浏览器. 在线预览 ...

随机推荐

  1. cpu降频问题

    cpu做为能耗很高的硬件,最近几年厂商在节能方面做了很多处理,在服务器运行时,基于负载情况可调节成节能模式,节省电能,副作用是cpu的频率会降低,导致应用程序性能降低. 有第三方统计,服务器规模达到万 ...

  2. angular学习笔记(三)-视图绑定数据的两种方式

    绑定数据有两种方式: <!DOCTYPE html> <html ng-app> <head> <title>2.2显示文本</title> ...

  3. 使用vuex保存singer每个歌星的基本信息

    1.建src/store文件夹,建立以下文件来存储歌星信息 2.state.js const state = { singer:{} } export default state 2.mutation ...

  4. Ajax读取XML和JSON数据

    Ajax从服务器获取的数据都是字符串,但是通过不同的解析,可以解析为XML或者JSON. 一般来说.使用XML格式的数据比较通用,但是服务器和客户端解析起来都比较复杂一些;而使用JSON语句话,服务端 ...

  5. Session 活化与钝化 与tomcat钝化驱动器

    1,绑定到Session中的 对象有多种状态,分别是   绑定   解除绑定     钝化    活化. 绑定 是保存,通过session.setattribute把对象保存到session的对象当中 ...

  6. hdu4366 Successor

    好题.   可是感觉题目描写叙述不是非常清楚 这题仅仅是询问开除某人后,他的下属中谁会替代他的位置.不会更新这个位置 要求一个子树中忠诚度最高的人. 能够想到dfs树.保留时间戳.每一个节点便表示一个 ...

  7. 【C#】删除集合(Collection)里的元素(Item)

    问题:C#中如果想要删除一个集合中的所有元素,直接for循环边读边删除是不可行的.因为每删除一个元素,后面的元素就会往前排,即它们的索引会向前-1,然后i还是正常的自增,就会跳过下一个元素. // 错 ...

  8. uWSGI的stats注释,送给需要的人,欢迎指正

    吐槽先,对于uWSGI状态信息没有文档说明这样一个现实,我只想说一句:F*CK YOU!!! 花了2天时间,累得眼珠子疼,针对这鬼畜的stats,借助Total Commander和VS大概撸了一边u ...

  9. Winform 加密连接字符串“未能提供RsaProtectedConfigurationProvider加密,对象已存在”的解决方案

    当一台机器已安装软件,并有新用户需要使用此软件时提示“未能提供RsaProtectedConfigurationProvider加密,对象已存在”. 这是因为加密模式是用户模式,需要运行以下脚本添加新 ...

  10. OK335xS 256M 512M nand flash make ubifs hacking

    /********************************************************************************* * OK335xs 256M 51 ...