查看原文
其他

教程 | 使用Unity制作2D动作游戏

Unity Unity官方平台 2019-05-07

无论项目使用3D环境还是2D环境,在Unity中构建战斗系统的过程并不简单。本文将由开发者Yusufbek Alimatov介绍实现Unity 2D动作游戏的基础功能,你可以通过本文介绍的方法开发出更为复杂的战斗系统。


资源项目

本文中工程项目代码和素材文件下载地址:

https://github.com/youbek/2DMeleeCombat


我们将使用到Asset Store资源商店中以下的免费资源。

  • Knight Sprite Sheet

    https://assetstore.unity.com/packages/2d/characters/knight-sprite-sheet-free-93897


  • Ninja Sprite Sheet

    https://assetstore.unity.com/packages/2d/characters/ninja-sprite-sheet-free-93901


  • 2D Game Starter Assets

    https://assetstore.unity.com/packages/2d/environments/2d-game-starter-assets-24626


我们将通过以下4个步骤实现项目:

  • 创建Unity 2D项目 

  • 从Assets Store资源商店下载并导入资源

  • 编写控制玩家移动的C#脚本并制作动画

  • 实现玩家的战斗过程


最终得效果如下图所示。


创建Unity 2D项目

首先在Unity中创建新项目。打开Unity编辑器,单击New按钮并命名项目,设置项目的保存位置,然后选择模板,不同的模板带有Unity提供的相应基础资源。


本项目我们将使用2D模板。


导入Asset Store资源商店中的资源

在本文的项目中,我们将使用Asset Store资源商店中的免费资源来构建环境,敌人和玩家。

  • Knight Sprite Sheet制作玩家

  • Ninja Sprite Sheet制作敌人

  • 2D Game Starter Assets用来构建环境

 

下载并导入资源后,请使用2D Game Starter Assets资源包按下图效果构造场景。



我们为环境部分设置了新的排序图层“env”,以避免角色被环境部分挡住。


添加一个空白游戏对象来保存地面部分。然后向该游戏对象添加Edge Collider 2D组件,并按照下图的效果进行修改。



我们添加Edge Collider 2D组件到地面游戏对象,以便使角色和地面发生碰撞。


编写控制玩家移动脚本并设置动画

本文的项目中,我们使用Knight Sprite Sheet资源制作玩家。


从Assets Store资源商店下载并导入资源后,我们会在Assets文件夹内看到Knight Files文件夹。打开Knight Files > Body > Knight,将Knight_idle_01从项目窗口拖到场景中。


我们可能无法在场景看见精灵,但精灵就在场景中,这是因为精灵位于默认的排序图层,而环境背景的排序图层为env,角色被环境背景挡住了。


解决方法:只要为角色设置另一个排序图层即可,我们将该排序图层命名为“Char”。



我们将角色的游戏对象名称从Knight_idle_01改为Player。现在我们给角色添加物理,使角色受重力影响,这样角色就不会像上图一样停留在空中。

 

在层级窗口中选中角色,单击Add Component,搜索并添加RigidBody2D组件和BoxCollider2D组件。添加组件后,角色会对物理效果产生反应。



效果不错,但是玩家对象的Box Collider区域比所需大小稍微大一些,所以要调整该区域的大小。 我们将Box Collider组件的Offset改为(0.03, -0.46),Size改为(0.74, 1.48)。



完成保存场景后,在Unity编辑器中创建Scripts和Animations文件夹,然后在Animations文件夹中创建PlayerAnimation和EnemyAnimation文件夹。

 

打开PlayerAnimation文件夹,在空白位置单击右键,选择Create > Animator Controller,创建Animator Controller文件并命名为PlayerAnimController。单击右键,选择Create > Animation创建三个动画,将它们分别命名为“Idle”,“Running”和“Attacking”。


我们给玩家对象附加Animator Controller组件,打开Animator Controller,将创建的动画拖到PlayerAnimController。



在Animator窗口添加isAttacking、isRunning、isIdle三个布尔值参数,它们分别代表:攻击、奔跑、空闲,最后我们在状态之间加入过渡。


  • 当isAttacking为true时,Idle转为Attacking

  • 当isAttacking为false且isIdle为true时,Attacking转为Idle

  • 当isRunning为true且isIdle为false时,Idle转为Running

  • 当isRunning为false且isIdle为true时,Running转为Idle

  • 当isAttacking为true时,Running转为Attacking

  • 当isAttacking为false且isRunning为true时,Attacking转为Running


除了Attacking转为Idle和Attacking转为Running,其它过渡状态都要取消勾选Has Exit Time。

 

最后,打开Assets > Knight Files > Knight PNG文件夹,通过使用其中的精灵图集制作奔跑,空闲和攻击动画,制作方法如下图所示。



上图是空闲动画的制作过程,你可以使用精灵图集,通过上图步骤做出奔跑和攻击动画。制作好攻击动画后,我们要添加一个点,用来决定近战武器是否对敌人造成伤害。

 

在Player游戏对象中,创建一个空白游戏对象并命名为DamageMaker。默认情况下,该对象处于不活动状态。

 

在攻击动画中,我们要将该对象位置按照剑的位置移动,在动画的第4帧,取消勾选DamageMaker,将其位置调整到剑的边缘。



现在返回Assets文件夹并打开Scripts文件夹,在空白位置单击右键,选择Create > C# Script,新建C#脚本并命名为PlayerMovement。我们将PlayerMovement脚本附加到Player游戏对象上,然后打开该脚本。

 

我们将根据以下输入来移动角色。

  • 按键“A”用来向左移动

  • 按键“D”用来向右移动

  • 鼠标左键用来进行攻击

 

PlayerMovement脚本包含玩家的血量和攻击力信息,我们首先向PlayerMovement脚本添加变量。

public class PlayerMovement:MonoBehaviour {
#region PUBLIC_VAR
#endregion
#region PRIVATE_VAR
[SerializeField] private Transform attackPoint;
[SerializeField] private float attackRadius;
[SerializeField] private float movementSpeed;
[SerializeField] private int damage;
#endregion


下面是以上代码的解释:

  • #region关键字可以让我们在使用Visual Studio的大纲显示功能时,指定想要折叠或展开的代码块。

  • Transform attackPoint会检查攻击时敌人的特定点。

  • Animator anim用于通过代码控制动画。

 

有些变量会从Player游戏对象获取组件信息,例如:本项目中的anim变量。在Start函数中编写以下代码。

anim = GetComponent <Animator>();


我们还要添加一些代码,使角色在玩家按下“A”和“D”键时移动。我们在Update函数中编写以下代码。

// 检查水平轴

float movement = Input.GetAxis("Horizontal") * Time.deltaTime * movementSpeed;

// 如果movement不等于0,这表示玩家按下了A或D,所以停止空闲动画,否则停止奔跑动画

if (movement != 0 && anim.GetCurrentAnimatorStateInfo(0).IsName("Attacking") == false)

{

anim.SetBool("isRunning", true);

anim.SetBool("isIdle", false);

// 如果movement值大于0,这表示玩家对象向右移动,所以将玩家对象向右转并进行移动

if (movement > 0)

{

transform.localScale = new Vector3(1, 1, 1);

transform.Translate(transform.right * movement);

}

else if (movement < 0)

{

transform.localScale = new Vector3(-1, 1, 1);

transform.Translate(transform.right * movement);

}

} else if(movement == 0 && anim.GetCurrentAnimatorStateInfo(0).IsName("Attacking") == false)

{

anim.SetBool("isRunning", false);

anim.SetBool("isIdle", true);

}


我们通过Input.GetAxis方法检查输入,然后通过变量检查玩家是否移动,是否正在播放攻击动画。

 

如果movement变量不等于0,而且没有播放攻击动画,这表示玩家调用了Input.GetAxis,从而知道玩家按下了和movement相关的按键,而且玩家没有处于攻击状态。因此在这种情况下要播放奔跑动画,否则播放空闲动画。

 

运行游戏前,在检视窗口将Player对象的movement speed值由0改为3,运行游戏后的效果如下图所示。


实现玩家的战斗过程

下面我们要实现近战攻击过程,代码如下所示。

// 如果点击了鼠标左键,播放攻击动画if (Input.GetMouseButtonDown(0))
{
anim.SetBool("isAttacking", true);
} else
{
anim.SetBool("isAttacking", false);
}
//检查attackPoint和damagemaker是否处于活动状态if(attackPoint.gameObject.active == true && damageMade == false)
{
damageMade = true;
Collider2D[] hittedObjects = Physics2D.OverlapCircleAll(attackPoint.position, attackRadius);
if(hittedObjects.Length > 0)
{
for(int i = 0; i < hittedObjects.Length; i++)
{
if(hittedObjects[i].gameObject != gameObject)
{
EnemyMovement enemy = hittedObjects[i].gameObject.GetComponent<EnemyMovement>();
if (enemy != null){
enemy.health -= damage;
}
}
}
}
} else if(attackPoint.gameObject.active == false && damageMade == true)
{
damageMade = false;
}


在上面的代码中,我们首先会检查是否按下了鼠标左键,如果按下了左键,播放攻击动画;如果没有按下左键,则停止播放攻击动画。

 

同时,我们会检查attackPoint是否处于活动状态,如果attackPoint处于活动状态,这表示角色可以通过该点伤害敌人。为了在attackRadius变量设定的半径内通过该点造成伤害,我们使用了Physics2D.OverlapCircle来获取所有带有碰撞体的对象。


然后我们会检查对象是否拥有EnemyMovement脚本,从而确定对象是否为敌人,如果带有该脚本,则对象为敌人,然后使敌人血量减去玩家伤害量。


小结

按照本文中的4个步骤,我们就实现了一个简单的2D动作游戏,希望大家学以致用,使用本文介绍的方法开发出更为复杂的战斗系统。

 

友情提示Unity 2D开发挑战赛12月18日星期二即将截至,希望参与本次挑战赛的开发者,一定要抓紧最后的时间,提交你所开发的 游戏,我们期待有更多精彩的Unity 2D作品。

 

更多Unity教程,尽在Unity官方中文论坛(UnityChina.cn)!

 

推荐阅读

官方活动

Unity 2D开发挑战赛(最后2天)

参加Unity 2D开发挑战赛,向全世界展示你在Unity 2D方面的创意实践。[了解详情...]

活动地址:

https://connect.unity.com/challenges/2dchallenge


Unity全球学生开发挑战赛

Unity面向全球的学生推出-Unity全球学生开发挑战赛,寻找全世界最具创意,展现自我的学生开发者团队。[了解详情...

活动地址:

https://connect.unity.com/challenges/gsc2018


Unity订阅圣诞福利

截至12月19日,Unity的新订阅用户在获得最高价值2800元的资源插件圣诞礼包的同时,我们将邀请活动期间所有的订阅用户参与Unity的圣诞派对,共庆年终圣诞季!

点击“阅读原文”访问Unity官方中文论坛

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存