说起炸弹超人,相信很多同学都玩过类似的游戏,其中最为大家熟知的莫过于《泡泡堂》,玩家扮演的的炸弹超人,把自己一肚子的炸弹放置在游戏世界里的各个角落,同时还要躲避敌方炸弹保护自己。初代的炸弹超人游戏都是2D的,而今天这篇文章将教大家如何在Unity中实现一款3D的炸弹超人游戏,现在就来看看怎么开始重制这款经典的游戏吧!
温馨提示,本教程需要大家了解Unity的基本操作与脚本概念。
**登录Unity官方中文论坛获得本文所需资源:
orum.china.unity3d.com/thread-24404-1-1.html**
准备工作
将项目初始资源导入Unity项目,资源目录如下:
其中分别包含要用于游戏的动画、材质、模型、背景音乐、物理材质、预制件、场景、脚本、音效及图片资源。
放置炸弹
打开项目中的Game场景并运行。
可以通过WASD键或方向键来操作所有角色进行移动。下面来让角色可以放置炸弹。角色1(红色)通过按下空格键来放置炸弹,角色2(蓝色)则通过按下回车键进行同样的操作。
打开Player脚本,该脚本负责角色所有的移动及动画逻辑。找到DropBomb函数,添加代码如下:
///
/// Drops a bomb beneath the player
///
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().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 = 1; i < 3; 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(0,.5f,0), 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(1, 2)] //Enables a nifty slider in the editor
public int playerNumber = 1; //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!”);
GlobalManager.PlayerDied(playerNumber); //Notify global state manager that this player died
Destroy(gameObject); } }
该函数作用为设置dead变量来通知玩家死亡,并告知全局状态管理器玩家的死亡信息,然后销毁玩家对象。
在检视面板中选中两个玩家对象,将Global State Manager游戏对象赋值给Player脚本的Global Manger字段。
再次运行场景,效果如下:
打开GlobalStateManager脚本,添加以下代码:
private int deadPlayers = 0;
private int deadPlayerNumber = -1;
public void PlayerDied(int playerNumber) {
deadPlayers++;
if (deadPlayers == 1) {
Invoke(“CheckPlayersDeath”, .3f); } }
其中deadPlayers表示死亡的玩家数量,deadPlayerNumber则用于记录死亡玩家的编号。PlayerDied函数用于添加死亡玩家,并设置deadPlayerNumber属性,在0.3秒后检测另一位玩家是否也死亡。
然后在脚本中添加CheckPlayersDeath函数,代码如下:
void CheckPlayersDeath() {
if (deadPlayers == 1) { //Single dead player, he’s the winner
if (deadPlayerNumber == 1) { //P1 dead, P2 is the winner Debug.Log(“Player 2 is the winner!”);
}
else { //P2 dead, P1 is the winner
Debug.Log(“Player 1 is the winner!”);
}
}
else { //Multiple dead players, it’s a draw
Debug.Log(“The game ended in a draw!”);
}
}
以上代码用于判断哪位玩家获得胜利,如果两位玩家均死亡,则打成平局。
运行场景,效果如下:
总结
到此本篇教程就结束了,大家还可以在此基础上对该项目进行扩展,例如添加“推箱子”功能,将位于自己脚边的炸弹推给敌方,或是限制能够放置的炸弹数量,添加快速重新开始游戏的界面,设置可以被炸弹炸毁的障碍物,设置一些道具用于获得炸弹或者增加生命值,还可以增加多人对战模式与朋友一起变身炸弹超人等等。大家都来发挥自己的创意吧!
“技术闪耀未来-Unity全球技术校园行”系列活动,为学习Unity的同学们带来了Unity Plus加强版开学季专属优惠,内涵一个价值数百美金的资源工具包,可助你提高开发效率,更高效的完成你的创意作品。
4款资源工具包包含有:VR、2D、艺术设计和移动平台资源包,每个资源工具包都包含有Asset Store中最受欢迎的资源和工具,可帮助您激发开发潜能,提升开发效率。使用资源工具助就你快速将理想变成现实。
- 移动平台工具包,价值188美金
包含节省调试时间,释放创造力的Editor Console Pro、轻松管理跨平台设置的Cross-platform Native Plugins-Ultra Pack、合并网格改善性能的Mesh Baker、快速开发移动平台触摸控件的Fingers Touch Gestures以及增强游戏画面性能的Fast Shadow Projector。
- VR 工具包,价值164美金
省时省力的Final IK、轻松创建VR环境UI的Curved UI、专业渲染360全景及4K视频的VR Panorama 360。
- 2D开发工具包,价值154美金
包含全平台解决方案,极致流畅开发的Corgi Engine、专注于游戏玩法而非UI代码的DoozyUI、轻松搞定UI动画与变换的DOTween Pro以及为2D游戏创造优质光照与阴影的2DDL Pro。
- 美术及设计工具包,价值160美金
包含关卡设计迭代更快的Octave3D、3A级着色器打造炫酷场景的UBER Standard Shader Ultra以及唯美特效烘托场景氛围Fog Volume
获得一款你的资源工具包,现在开启一场创作之旅!
“技术闪耀未来-Unity全球技术校园行”- Unity Plus加强版开学季专属优惠(优惠期9月1日-9月30日):
1, 特惠价格139元/月订阅价
2, 免费获得Unity认证开发者课程(访问权截止到12月31日)
3, 免费获得1款资源工具包:VR、2D、艺术设计和移动平台(4选1)
点击此链接,完成订阅购买:https://store.unity.com/cn/offer/unity-essentials-education-packs?login=1