怎样使用Unity3D开发Flappy Bird游戏

这是一个教你怎样使用Unity3D制作Tappy Plane(Flappy Bird克隆版)的教程。如果你是有一些C#编程经验的Unity 2D游戏开发者,这个教程正适合你。现在让我们开始吧。

原文网址:http://anwell.me/articles/unity3d-flappy-bird/

完整工程代码在这里下载(https://github.com/anwell/TappyPlane)

安装Unity


Unity3D是个免费的游戏开发引擎。虽然Unity3D的名字中有个“3D”,但它最近发布的版本已经支持2D游戏的开发。使用Unity创建出来的游戏,可以运行在iOS,Android,Windows Phone,网页和其它许多平台上。


创建新的工程


在“Create New Project”窗口,修改窗口底部的默认设置为“2D”,工程名称为“TappyPlane”,然后点击“Create”按钮。


组织你的工程


创建工程后,应该能看到这样一个空窗口。


unity手机游戏开发 pdf unity如何开发手机游戏_unity手机游戏开发 pdf



在“Project”面板下创建文件夹来存放你需要的文件,增加的4个文件夹名称分别为“Prefabs”,“Scenes”,“Scripts”,以及“Textures”。以下是每种文件夹的作用说明。



Prefabs


在Unity中,Prefab是一个可以重新创建和使用的对象,例如:子弹,敌人,或者墙。



Scenes


一个Scene等同于游戏的一个关卡。



Scripts


这个目录下存放所有代码。



Textures


所有游戏中使用的图片。在2D游戏中,这些图片被称为“Sprites”。



设置背景


保存这张图片到刚才创建的Textures文件夹中。


unity手机游戏开发 pdf unity如何开发手机游戏_游戏开发_02



拖放这张图片到Scene视图的中心位置。在Inspector面板,设置Scale的x和y值都为2.5。



增加主角


保存这张图片到Textures文件夹下。和设置背景一样,拖放这张图片到Scene视图。


unity手机游戏开发 pdf unity如何开发手机游戏_游戏开发_03



在Inspector面板,点击“Add Component”,找到“Rigidbody 2D”,点击确定。使用Rigidbody组件来给这架飞机增加重力和其它物理特性。


点击屏幕上方的三角形“Play”按钮,你将看到飞机随着重力而向下坠落。


控制主角


现在我们创建一个脚本让主角移动起来。在Scripts文件夹,创建一个名为Player.cs的C#文件,代码如下:


using UnityEngine;

public class Player : MonoBehaviour
{
// The force which is added when the player jumps
// This can be changed in the Inspector window
public Vector2 jumpForce = new Vector2(0, 300);

// Update is called once per frame
void Update ()
{
// Jump
if (Input.GetKeyUp("space"))
{
rigidbody2D.velocity = Vector2.zero;
rigidbody2D.AddForce(jumpForce);
}
}
}


代码中需要关注的两点是:jumpForce变量和update方法。


jumpForce:用来存储跳起时作用在主角身上的力。用Vector2类型,意味着它只有2个值:x和y。这个变量是public类型,你可以在Inspector面板中修改它的值。


Update方法:在游戏中的每一帧都被调用。如果按下空格键,会有一个力作用到rigidbody对象。


和前面增加RigidBody 2D组件的方法一样,使用“Add Component”把这个脚本挂载到主角对象上。现在点击“Play”,可以跳跃和下落了。


创建障碍物


unity手机游戏开发 pdf unity如何开发手机游戏_游戏_04

 


                

               

unity手机游戏开发 pdf unity如何开发手机游戏_游戏_05



保存这2张图片到Textures文件夹,拖拉它们到Scene视图,在Inspector面板,修改Scale的X和Y值为2.5。


移动这些对象,使它们位于背景之上,并且上下缝隙足够宽使得主角能越过它们。


在File菜单,GameObject -> Create Empty,这将会增加一个对象到场景,它是不可见的,作为整合我们的岩石障碍物的一个目录。改变名字为“RockPair”。拖拉这2个岩石对象到“RockPair”下。


移动障碍物


增加一个“RigidBody 2D”组件给RockPair父对象。在Inspector面板,勾选上Is Kinematic,这将使障碍物不会受到重力影响。


unity手机游戏开发 pdf unity如何开发手机游戏_unity手机游戏开发 pdf_06

创建另一个名为Obstacle.cs的脚本,放在Scripts目录下。这个脚本用来把岩石从屏幕右边移动到左边。代码如下:

using UnityEngine;

public class Obstacle : MonoBehaviour
{
public Vector2 velocity = new Vector2(-4, 0);

// Use this for initialization
void Start()
{
rigidbody2D.velocity = velocity;
}
}


当对象创建时,Start方法只运行一次。因此,我们设置这个对象的速率在x方向的值为-4.


把这个脚本挂载到RockPair对象,点击Play按钮,会看到障碍物慢慢横穿过屏幕。



动态生成障碍物


我们需要每隔几秒创建出新的岩石障碍。首先,把RockPair对象拖到Prefabs文件夹下,这会把RockPair对象变成一个可以创建和销毁许多次的Prefab。接着在Scene场景窗口中删除RockPair。


创建一个空对象,修改名字为“Scripts”。再创建一个名为Generate.cs的脚本,输入以下代码,并且把Generate脚本挂载到刚创建出来的Scripts对象。


using UnityEngine;

public class Generate : MonoBehaviour
{
public GameObject rocks;

// Use this for initialization
void Start()
{
InvokeRepeating("CreateObstacle", 1f, 1.5f);
}
void CreateObstacle()
{
Instantiate(rocks);
}
}



在这个脚本中,我们使用了InvokeRepeating方法,这个方法的功能是每隔若干秒调用一次指定函数。第一个参数是字符串,代表着要调用的函数名称。第二个参数代表延迟几秒后调用这个函数。第三个参数是每一次调用之间的间隔秒数。


在CreateObstacle方法中,我们使用了Instantiate,这个方法的功能是生成一个新的Prefab到场景中,这里我们增加到场景中的新Prefab是个叫rocks的变量。但这个变量还没有和我们的RockPair关联起来,所以,现在把RockPair prefab从它的目录中拖放到Inspector的rocks值中,就像下面这样。


试着运行代码,你能看到每隔1.5秒会生成新的障碍。



销毁主角


你可能已经注意到那个障碍物什么作用也没有,让我们给这个碰撞加点什么吧。


单击player对象,增加一个叫“Box Collider 2D”的组件。


现在选定RockPair预制件,单击小箭头。给第一个对象增加一个叫“Polygon Collider 2D”的组件,对另外一个障碍同样这样做。


一个碰撞器组件是一个触发碰撞的形状,运行游戏看看发生了什么,看起来有点乐趣了。


当主角和障碍物碰撞时,需要让游戏重新启动。我们继续编辑Player.cs文件,代码如下:


using UnityEngine;

public class Player : MonoBehaviour
{
// The force which is added when the player jumps
// This can be changed in the Inspector window
public Vector2 jumpForce = new Vector2(0, 300);

// Update is called once per frame
void Update ()
{
// Jump
if (Input.GetKeyUp("space"))
{
rigidbody2D.velocity = Vector2.zero;
rigidbody2D.AddForce(jumpForce);
}

// Die by being off screen
Vector2 screenPosition = Camera.main.WorldToScreenPoint(transform.position);
if (screenPosition.y > Screen.height || screenPosition.y < 0)
{
Die();
}
}

// Die by collision
void OnCollisionEnter2D(Collision2D other)
{
Die();
}

void Die()
{
Application.LoadLevel(Application.loadedLevel);
}
}


在Update方法中,我们增加了一些代码用来检测主角的位置是否在屏幕里面。如果不是,主角将会死掉。


无论这个脚本附加在哪个游戏对象身上,transform都用来处理位置、旋转和比例。


Die方法将使关卡重置。


无论何时,两个有Collider 2D组件的游戏对象产生碰撞,都会调用OnCollisionEnter2D方法。


运行游戏,每次主角死亡或飞出屏幕,游戏都会重新开始。



增加一点随机性


如果你现在玩这个游戏,会感觉到一点。。。无聊。我们需要让障碍物的高度有变化,使得它更有挑战性。Obstacle.cs的代码更新如下:


using UnityEngine;

public class Obstacle : MonoBehaviour
{
public Vector2 velocity = new Vector2(-4, 0);
public float range = 4;

// Use this for initialization
void Start()
{
rigidbody2D.velocity = velocity;
transform.position = new Vector3(transform.position.x, transform.position.y - range * Random.value, transform.position.z);
}
}


range是表示随机范围的变量,这个数字越大,岩石位置的变化幅度也越大。你可以调整这个参数以便适合自己的游戏。


当岩石对象第一次创建时,我们移动它的位置到一个随机量。



计分


最后,让我们计分吧。更新Generate.cs文件的代码如下:


using UnityEngine;

public class Generate : MonoBehaviour
{
public GameObject rocks;
int score = 0;

// Use this for initialization
void Start()
{
InvokeRepeating("CreateObstacle", 1f, 1.5f);
}

// Update is called once per frame
void OnGUI () 
{
GUI.color = Color.black;
GUILayout.Label(" Score: " + score.ToString());
}

void CreateObstacle()
{
Instantiate(rocks);
score++;
}
}


我们用一个整数来计分。


OnGUI方法每一帧被调用若干次,用来显示文本和按钮。这里我们用黑色文本来把分数放在屏幕左上角。


每创建一个新岩石,加一分。



保存你的工作


点击菜单File -> Save,保存这个关卡到Scenes文件夹,命名为Play.unity,恩,大功告成了。


unity手机游戏开发 pdf unity如何开发手机游戏_unity手机游戏开发 pdf_07



就这些了


恭喜,你用Unity完成了一个Flappy Bird克隆版,你可以用自己的想法和美术来任意改变这个游戏,这里还有几项需要优化:


目前,我们创建了新的障碍物,但从来没有销毁它。运行一段时间后,这个游戏会变慢很多。


没有提示菜单或开始画面。