目录

Unity-4.3-制作一个2D横版射击游戏

Unity 4.3 制作一个2D横版射击游戏

这是一个横版射击游戏。 教程来自:

中文版教程:

教程文章已经详细地介绍实现过程,这里就不再复述,只做一些简单的笔记记录,以供备忘。

1.创建第一个场景

新建工程。接着在" Project “面板上创建如下文件夹:

https://img-blog.csdn.net/20140409123230250?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWtvZjEzMTQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

接着在” Hierarchy “面板上创建多个空对象,形成以下结构:

https://img-blog.csdn.net/20140409123324906?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWtvZjEzMTQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

这些空对象的 Position 保持为(0, 0, 0)即可。保存场景,名称为” Stage1 “。

2.添加显示背景

将背景图片放入” Textures “文件夹,确认这张图片的纹理类型,即” Texture Type “属性为” Sprite “,如下图所示:

https://img-blog.csdn.net/20140409123411968?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWtvZjEzMTQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

在场景中添加一个Sprite游戏对象,设置其” Sprite “属性为刚才导入的背景图片。重命名这个对象为” Background1 “,将其移动到” Level -> 0 - Background “里面,设置其” Position “为 (0, 0, 0)。接着添加背景元素。导入平台图片到

" Textures “文件夹,选中”

platforms “图片,设置其”

Sprite Mode “为”

Multiple “,然后点击”

Sprite Editor “,如下图所示:

https://img-blog.csdn.net/20140409123503000?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWtvZjEzMTQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

在弹出的” Sprite Editor “窗口中,进行绘制每个平台的包围矩形,以便将纹理分割成更小的部分。然后分别命名为” platform1 “和” platform2 “,如下图所示:

https://img-blog.csdn.net/20140409123526031?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWtvZjEzMTQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

创建一个新的 Sprite游戏对象,设置其” Sprite “属性为”

platform1 “。再在创建新

Sprite对象,

设置其” Sprite “属性为”

platform2 “。将它们放置到”

1 - Middleground “对象里,并且确认它们的Z坐标为0。将这两个对象从”

Hierarchy “面板拖动到”

Project “面板下的”

Prefabs “文件夹,保存成预制对象。接着,为了避免显示顺序问题,修改下游戏对象的Z坐标,如下所示:

LayerZ Position
0 - Background10
1 - Middleground5
2 - Foreground0

此时,点击” Scene “面板上的2D到3D视图切换,可以清楚看到层次:

https://img-blog.csdn.net/20140409151826750

3.创建主角和敌人

导入主角图片 到

" Textures “文件夹,创建一个Sprite游戏对象,命名为” Player “,

设置其” Sprite “属性为刚才导入的主角图片。将此对象放入”

2 - Foreground “层里,设置其 Scale

(0.2, 0.2, 1)。接着,为主角添加盒碰撞体组件,点击”

Add Component “按钮,选择”

Box Collider 2D “,设置其 Size

(10, 10),虽然这还是大于实际的区域,但已比图片小多了,如下图所示:

https://img-blog.csdn.net/20140409123702968?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWtvZjEzMTQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

(可以通过按住Shift键,来调整绿色碰撞范围)

接着,再为主角对象添加” Rigidbody 2D “刚体组件,现在运行可以看到如下结果:

https://img-blog.csdn.net/20140409123821531

可以看到主角往下落了,这是因为刚体带有重力,但在这个游戏不需要用到,将” Gravity Scale “属性设为0即可。另外,不想因为物理而引起的主角旋转,则将” Fixed Angles “属性勾选上。完整的设置如下图所示:

https://img-blog.csdn.net/20140409123859953

导入子弹图片 到

" Textures “文件夹,创建一个Sprite游戏对象,命名为” PlayerShot

“,

设置其” Sprite “属性为刚才导入的图片

,设置”

Scale “属性为 (0.75, 0.75, 1) ,添加” Rigidbody 2D “组件,其” Gravity Scale “属性为0,并且勾选” Fixed Angles “属性框

,添加” Box Collider 2D “组件,其 Size 为(1, 1),并且勾选”

IsTrigger “属性

。勾选”

IsTrigger “属性表示该碰撞体用于触发事件,并将被物理引擎所忽略。意味着,子弹将穿过触碰到的对象,而不会阻碍对象的移动,触碰的时候将会引发”

OnTriggerEnter2D “事件。创建一个脚本,命名为”

ShotScript “,代码如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25using UnityEngine; /// /// Projectile behavior /// public class ShotScript : MonoBehaviour { // 1 - Designer variables /// /// Damage inflicted /// public int damage = 1 ; /// /// Projectile damage player or enemies? /// public bool isEnemyShot = false ; void Start() { // 2 - Limited time to live to avoid any leak Destroy(gameObject, 20 ); // 20sec } }

将此脚本附加到子弹对象上,然后将” MoveScript “脚本也附加到子弹对象上以便可以移动。保存此对象为预制。接着,让碰撞产生伤害效果。创建一个脚本,命名为” HealthScript “,代码如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49using UnityEngine; /// /// Handle hitpoints and damages /// public class HealthScript : MonoBehaviour { /// /// Total hitpoints /// public int hp = 1 ; /// /// Enemy or player? /// public bool isEnemy = true ; /// /// Inflicts damage and check if the object should be destroyed /// /// <param name=“damageCount”> public void Damage( int damageCount) { hp -= damageCount; if (hp <= 0 ) { // Dead! Destroy(gameObject); } } void OnTriggerEnter2D(Collider2D otherCollider) { // Is this a shot? ShotScript shot = otherCollider.gameObject.GetComponent(); if (shot != null ) { // Avoid friendly fire if (shot.isEnemyShot != isEnemy) { Damage(shot.damage); // Destroy the shot Destroy(shot.gameObject); // Remember to always target the game object, otherwise you will just remove the script } } } }

将此脚本附加到 Poulpi 预制体上。现在运行,让子弹和章鱼碰撞,可以看到如下结果:

https://img-blog.csdn.net/20140409124044203

如果章鱼的生命值大于子弹的伤害值,那么章鱼就不会被消灭,可以试着通过改变章鱼对象的” HealthScript “的hp值。接着,准备可以射击。创建一个脚本,命名为” WeaponScript “,代码如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86using UnityEngine; /// /// Launch projectile /// public class WeaponScript : MonoBehaviour { //——————————– // 1 - Designer variables //——————————– /// /// Projectile prefab for shooting /// public Transform shotPrefab; /// /// Cooldown in seconds between two shots /// public float shootingRate = 0 .25f; //——————————– // 2 - Cooldown //——————————– private float shootCooldown; void Start() { shootCooldown = 0f; } void Update() { if (shootCooldown > 0 ) { shootCooldown -= Time.deltaTime; } } //——————————– // 3 - Shooting from another script //——————————– /// /// Create a new projectile if possible /// public void Attack( bool isEnemy) { if (CanAttack) { shootCooldown = shootingRate; // Create a new shot var shotTransform = Instantiate(shotPrefab) as Transform; // Assign position shotTransform.position = transform.position; // The is enemy property ShotScript shot = shotTransform.gameObject.GetComponent(); if (shot != null ) { shot.isEnemyShot = isEnemy; } // Make the weapon shot always towards it MoveScript move = shotTransform.gameObject.GetComponent(); if (move != null ) { move.direction = this .transform.right; // towards in 2D space is the right of the sprite } } } /// /// Is the weapon ready to create a new projectile? /// public bool CanAttack { get { return shootCooldown <= 0f; } } }

将这个脚本附加到主角对象上,设置其” Shot Prefab “属性为” PlayerShot “预制体。打开” PlayerScript “脚本,在 Update ()方法里面,加入以下片段:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21void Update() { // … // 5 - Shooting bool shoot = Input.GetButtonDown( “Fire1” ); shoot 

当收到射击的按钮状态,调用 Attack(false) 方法。现在运行,可以看到如下结果:

https://img-blog.csdn.net/20140409124222562

接下来,准备创建敌人的子弹。 导入敌人子弹图片

" Textures “文件夹,

选中” PlayerShot “预制体,按下 Ctrl+D 进行复制,命名为” EnemyShot1 “,然后改变其 Sprite 为刚才导入的图片,设置其 Scale

(0.35, 0.35, 1)。接着,让章鱼可以射击。将”

WeaponScript “脚本附加到章鱼对象上,拖动”

EnemyShot1 “预制体到其”

Shot Prefab “属性,创建一个脚本,命名为”

EnemyScript “,用来简单地每一帧进行自动射击,代码如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24using UnityEngine; /// /// Enemy generic behavior /// public class EnemyScript : MonoBehaviour { private WeaponScript weapon; void Awake() { // Retrieve the weapon only once weapon = GetComponent(); } void Update() { // Auto-fire if (weapon != null && weapon.CanAttack) { weapon.Attack( true ); } } }

将此脚本附加到章鱼对象上,如下图所示:

https://img-blog.csdn.net/20140409124255343

现在运行,可以看到如下结果:

https://img-blog.csdn.net/20140409124323562

可以看到章鱼向右射击了子弹,这是因为代码就是让它那么做的。实际上,应该做到可以朝向任何方向射击子弹。在这里,创建一个空对象,命名为” WeaponObject “,删除章鱼预制体身上的” WeaponScript “脚本,将” WeaponScript “脚本附加到” WeaponObject “对象上,并且 拖动”

EnemyShot1 “预制体到其”

Shot Prefab “属性,设置 " WeaponObject “对象的” Rotation “属性为(0, 0, 180),然后保存为预制,如下所示:

接着,修改” EnemyScript “,代码为如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28using System.Collections.Generic; using UnityEngine; /// /// Enemy generic behavior /// public class EnemyScript : MonoBehaviour { private WeaponScript[] weapons; void Awake() { // Retrieve the weapon only once weapons = GetComponentsInChildren(); } void Update() { foreach (WeaponScript weapon in weapons) { // Auto-fire if (weapon != null && weapon.CanAttack) { weapon.Attack( true ); } } } }

可以适当调整子弹的移动速度,它应该快于章鱼的移动速度。现在运行,如下图所示:

https://img-blog.csdn.net/20140409124348984

按这种方式,可以轻易实现多个方向的射击。复制添加一个” WeaponObject “对象,让这两个” WeaponObject “对象的旋转不同即可。现在主角被章鱼攻击到,但是没有任何伤害。将” HealthScript “脚本附加到主角对象上,确保” Is Enemy “属性不被勾选。现在运行,可以看到如下结果:

https://img-blog.csdn.net/20140409124417453

目前,当主角和章鱼碰撞时,仅仅只是阻碍对方的移动而已,在这里改成互相受到伤害。打开” PlayerScript “文件,添加如下代码:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25//PlayerScript.cs //…. void OnCollisionEnter2D(Collision2D collision) { bool damagePlayer = false ; // Collision with enemy EnemyScript enemy = collision.gameObject.GetComponent(); if (enemy != null ) { // Kill the enemy HealthScript enemyHealth = enemy.GetComponent(); if (enemyHealth != null ) enemyHealth.Damage(enemyHealth.hp); damagePlayer = true ; } // Damage the player if (damagePlayer) { HealthScript playerHealth = this .GetComponent(); if (playerHealth != null ) playerHealth.Damage( 1 ); } }

至此,一个基本的射击游戏完成。 ,将进行增强表现,完善游戏。