您好,欢迎来到好走旅游网。
搜索
您的当前位置:首页(译)【Unity教程】使用Unity开发WindowsPhone上的横版跑酷游戏

(译)【Unity教程】使用Unity开发WindowsPhone上的横版跑酷游戏

来源:好走旅游网
(译)【Unity教程】使⽤Unity开发WindowsPhone上的横版跑

酷游戏

译者注:

⽬前移动设备的跨平台游戏开发引擎基本都是采⽤Cocos2d-x或者Unity。⼀般⽽⾔2d⽤cocos2d-x 3d⽤unity,但是对于Windows Phone开发者,

cocos2d-x for wp8是微软维护的,版本升级⼗分缓慢,到现在还是 V2.0 preview,我们不可能拿⼀个不太稳定的版本去开发游戏。与之相反,Unity4.2发布之后,

⽀持WP8和Windows8,当然也包括其他平台,开发调试都是⼗分便捷,因此使⽤Unity来开发⽬标⽤户在WP上的游戏,是个很好的选择。

这是⼀篇译⽂,原⽂很长,于是我把它分成了两部分,⽽且加⼊了⾃⼰的⼀些修改和理解,点击⼀下链接观看第⼀部分效果。(需要安装最新的unity插件)

原⽂:

在这篇教程⾥,我们将学习如何去制作⼀款简单的⽆尽跑酷游戏,在这⾥你将学到:

⽣成⼀个分层的背景重⽤对象使⽤物理引擎

通过检测输⼊来控制玩家跳跃实现能量增加

⼀个简单的事件管理器按需控制物体的开关制作⼀个简单的GUI

在开始之前,我们应该先考虑⼀下在游戏⾥⾯加⼊什么。我们要做的是⼀个2D侧卷轴游戏,但是还是太宽泛了,让我们来缩⼩⼀下范围。

游戏的玩法:我们将控制⼀个⼈物不断的向屏幕右侧奔跑,从⼀个平台跳到另外⼀个平台,要跑的尽可能的远。这些平台有不同的特性,

有的会让你加速,

有的会让你减速。我们还包含单⼀的能量球,可以让你在空中跳跃。

游戏图形:我们将使⽤纯Cube和标准的粒⼦系统来制作(程序员的悲哀。。。) 玩家,平台,包括背景,统统都是Cube,⽽粒⼦系统将

被⽤于制作运动轨迹,

很多漂浮物将会给⼈更好的速度和深度的感觉。另外,游戏不包括特效⾳和背景⾳。

打开Unity,创建⼀个新的⼯程,不要导⼊任何的包。

我们是要做的2D视⾓的游戏,但是还想有⼀点3D的效果,Orthographic摄像机是不能⽤于3D游戏的,因此我们得采⽤默认的Perspective类型。这样的话,将物体放到离镜头不同的距离,我们就能得到⼀个分层的滚动背景。

就让我们假定,前景是在距离0,第⼀个背景在距离50,第⼆个背景在距离100。让我们分别放三个Cube在这三个深度,并且将他们作为创建场景的引导者。我⾃⼰已经试过了⼀些⾓度和颜⾊组合,觉得还可以,当然你也可以⾃⼰去实验⼀些新的数值。

下⾯正式开始:

⾸先添加⼀个平⾏光(GameObject->Create Other->Directional Light),设置旋转为(20,330,0)然后设置摄像机的参数,颜⾊为(115,140,220)其他数值见图:

创建3个Cube, Position 分别是(0,0,0) (0,0,50) (0,0,100),名字对应的是 Runner, Skyline Close, Skyline Far Away,后两个SkylineCube 不需要

碰撞器(Box Collider),直接在属性⾯板⾥,右键移除组件即可。 Runner是这次游戏的猪觉,在这⾥我称之为 “奔跑者”,后⾯同之。给3个Cube分别创建材质(Project 视图,Create-> Material),命名为Runner Mat, Skyline Close Mat, Skyline Far Away Mat. 然后分别拖放到对应的Cube上。

我使⽤了默认的 diffuse Shader , 颜⾊分别设为, White, (100, 120, 220), (110, 140, 220), 设置完成后的值如下:

为了使项⽬的组织架构更好,我们在Project视图⾥增加2个⽂件夹,Runner, Skyline, 然后把材质放到对应的⽂件夹⾥。运⾏⼀下,可以看到3个Cube都出现在了视野⾥⾯。

开始跑步吧 到⽬前为⽌,我们做的还没什么奇特的,场景⾥⾯什么也没有发⽣,但是接下来就是见证奇迹的时刻了。让我们来让 “奔跑者” 向右边移动来模拟⼀下这个游戏吧。在Runner⽂件夹⾥创建⼀个C#脚本,Runner.cs

using UnityEngine;

using System.Collections;

public class Runner : MonoBehaviour {

// Use this for initialization void Start () { }

// Update is called once per frame void Update () {

transform.Translate(5f * Time.deltaTime, 0f, 0f); }}

把脚本拖到层次视图的Runner 上⾯,运⾏,怎么样,看到主⾓开始跑了吧。但是有个问题,摄像头没有跟随它在运动,没⼀会就跑出我们的视野了,

这样的游戏根本没法玩啊,也不是我们想要的。解决的⽅法很简单,把摄像机对象拖到Runner⾥,让他成为Runner的Child. 现在再运⾏的话就没有问题了,⽽且我们可以发现,远处的Cube要⽐进出的Cube移动的好像快⼀些,当然这就是视差的问题了。

⽣成天际线 现在我们已经有了基本的运动了,接下来让我们⽣成⼀⾏的Cube来实现⽆⽌境的天际线。⾸先有件事情我们必须意识到,名为⽆尽的,其实只需要⼀部分存在地图中就可以了,

因为随着镜头不断的右移,左侧的天际线不断消失在视野中,他们是可以被销毁的,没有必要再继续占⽤资源了。或者,我们可以将它移动位置,在右侧重建场景,省去了重复的创建开⽀。

通过这个特性,我们只需要很少的资源就可以创建⽆⽌尽的天际线了。

在Skyline ⽂件夹中创建⼀个SkylineManager的脚本,因为要通过⼀个脚本创建两个天际线,所以需要传⼀个值进来,知道是要创建具体哪种。

public Transform prefab;

同样的,为了场景层次视图中的组织结构友好,我们需要设置⼀下层次。 ⾸先新建⼀个空对象,起名Managers, 作为⽗容器。然后给它创建⼀个⼦对象 Skyline Close Manager,然后把脚本拖到这个对象上来。

接下来把Skyline Close和Skyline Far Away 这两个Cube拖拽到Project中的Skyline⽂件夹下,使之成为Prefab,然后将层次视图中的两个对象删除,

设置好之后,层次视图和Project视图如下所⽰:

现在我们需要⼀个起点指⽰我们从哪⾥开始构建天际线,我们可以通过Manger对象本⾝的位置,⽽且我们需要⼀个数量值来决定多少个Cube组合起来才能填充完屏幕,

新建⼀个变量叫做 numberOfObjects ,另外声明⼀个变量 nextPosition ,指⽰左边的对象⽆效之后,应该在哪⾥重建。

public Transform prefab;public int numberOfObjects;private Vector3 nextPosition;

void Start(){

nextPosition = transform.localPosition;}

下⼀步是创建初始⾏的Cube,通过⼀个for循环来实现,实例化我们之前创建为prefab的Cube,每⼀个cube的位置都是nextPosition,⽽且随着没添加⼀个动态修改这个变量的值

void Start(){

nextPosition = transform.localPosition; for (int i = 0; i < numberOfObjects; i++) {

Transform o = (Transform)Instantiate(prefab); o.localPosition = nextPosition; nextPosition.x += o.localScale.x; }}

现在设置Skyline Close Manager 的Position 为(0, -1, 0) 并且设置 numberOfObjects 变量的值为10 ,运⾏

可以看到出现了⼀连串的Cube了,有点“地平线”的影⼦了,但是有个问题就是“天际线”本⾝不会随着镜头运动,去往左侧就消失不见了。我们回收重⽤Cube的策略是只回收那些离玩家超过⼀定距离的,因此⼀定要知道玩家跑了有多远,为了达到这个⽬的,我们在 Runner.cs⾥

添加⼀个静态变量,⽽且时时更新它。

public static float distanceTraveled;// Use this for initializationvoid Start () { }

// Update is called once per frame

void Update () {

  transform.Translate(5f * Time.deltaTime, 0f, 0f); //因为起始位置是 0

  distanceTraveled = transform.position.x;}

现在我们将要把我们的组成地平线的物体放到⼀个队列⾥,并且不断的检查是否要回收,因为是队列,只需要检查第⼀个即可,如果是需要回收,

从队列中移除,修改位置,然后放到队列最后边就可以了。

我们⽤⼀个recycleOffset变量来配置具体物体落后玩家多远的话 可以回收,这⾥设置为 60 .

public class SkylineManager : MonoBehaviour { public Transform prefab; public int numberOfObjects; public float recycleOffset;

private Vector3 nextPosition;

private Queue objectQueue;

void Start() {

objectQueue = new Queue(numberOfObjects); nextPosition = transform.localPosition;

for (int i = 0; i < numberOfObjects; i++) {

Transform o = (Transform)Instantiate(prefab); o.localPosition = nextPosition; nextPosition.x += o.localScale.x; objectQueue.Enqueue(o); } }

// Update is called once per frame void Update () {

if (objectQueue.Peek().localPosition.x + recycleOffset < Runner.distanceTraveled) {

Transform o = objectQueue.Dequeue(); o.localPosition = nextPosition; nextPosition.x += o.localScale.x; objectQueue.Enqueue(o); } }}

现在运⾏,在Scene视图⾥,可以看到Cube⾏ 是随着 “奔跑者” 不断的重新修正⾃⼰的位置的。但是他现在看起来还不像天际线,为了⽣成更像实际的

没有规则的天际线,让我们在它⽣成或者充值的时候随机放⼤它。

⾸先考虑到会有重复的代码产⽣,⾸先写个函数Recycle ,在start或者update的时候都调⽤它。

public class SkylineManager : MonoBehaviour{

public Transform prefab; public int numberOfObjects; public float recycleOffset;

private Vector3 nextPosition;

private Queue objectQueue;

void Start() {

objectQueue = new Queue(numberOfObjects); for (int i = 0; i < numberOfObjects; i++) {

objectQueue.Enqueue((Transform)Instantiate(prefab)); }

nextPosition = transform.localPosition; for (int i = 0; i < numberOfObjects; i++) {

Recycle(); } }

void Update()

{

if (objectQueue.Peek().localPosition.x + recycleOffset < Runner.distanceTraveled) {

Recycle(); } }

private void Recycle() {

Transform o = objectQueue.Dequeue(); o.localPosition = nextPosition; nextPosition.x += o.localScale.x; objectQueue.Enqueue(o); }}

下⼀步,让我们加⼊两个变量分别表⽰允许的放⼤最⼤和最⼩值,当放⼤⼀个物体之后,我们要确定可以保证后⾯的物体和前⾯的都是底部对齐的,

public class SkylineManager : MonoBehaviour{

public Transform prefab; public int numberOfObjects; public float recycleOffset; public Vector3 minSize, maxSize; private Vector3 nextPosition;

private Queue objectQueue;

void Start() {

objectQueue = new Queue(numberOfObjects); for (int i = 0; i < numberOfObjects; i++) {

objectQueue.Enqueue((Transform)Instantiate(prefab)); }

nextPosition = transform.localPosition; for (int i = 0; i < numberOfObjects; i++) {

Recycle(); } }

void Update() {

if (objectQueue.Peek().localPosition.x + recycleOffset < Runner.distanceTraveled) {

Recycle(); } }

private void Recycle() {

Vector3 scale = new Vector3(

Random.Range(minSize.x, maxSize.x), Random.Range(minSize.y, maxSize.y), Random.Range(minSize.z, maxSize.z)); Vector3 position = nextPosition; position.x += scale.x * 0.5f; position.y += scale.y * 0.5f;

Transform o = objectQueue.Dequeue(); o.localScale = scale;

o.localPosition = position; nextPosition.x += scale.x; objectQueue.Enqueue(o); }}

为了得到⼀个漂亮的天际线效果,把这个Manager放到(-60,-60, 50),并且将MinSize 设置为(10,20,10) MaxSize设置为(30,60,10)Recycle Offset 设置为60

让我们继续添加第⼆个天际线层,选中Skyline Close Manager \"CTRL+D \" 复制⼀份,并且改名为 Skyline Far Away Manager, 将它的prefab属性改为 Skyline Far Away 这个预设。

它的位置设置为(-100,-100, 100) 它的Recycle Offset 为 75,MinSize为(10,50,10) MaxSize为(30,100,10) 当然你也可以照你⾃⼰的喜好来设置新的值

产⽣平台

⽣成平台跟⽣成天际线很像,稍微有点不同的是平台的⾼度需要随机设定,⽽且他们之间需要有沟壑。并且我们需要约束平台的⾼度,好让它不会影响天际线的显⽰,

如果平台超出这个范围了,我们需要给它纠正过来。

在Project视图⾥新建⼀个⽂件夹,取名字叫做Platform, 然后在⾥⾯创建⼀个C#脚本,叫做 PlatformManager, 然后把SkylineManager的脚本拷贝到这⾥来,修改⼀部分源码如下:

public class PlatformManager : MonoBehaviour { public Transform prefab; public int numberOfObjects; public float recycleOffset;

public Vector3 minSize, maxSize, minGap, maxGap;

public float minY, maxY;

private Vector3 nextPosition;

private Queue objectQueue;

void Start() {

objectQueue = new Queue(numberOfObjects); for (int i = 0; i < numberOfObjects; i++) {

objectQueue.Enqueue((Transform)Instantiate(prefab)); }

nextPosition = transform.localPosition; for (int i = 0; i < numberOfObjects; i++) {

Recycle(); } }

void Update() {

if (objectQueue.Peek().localPosition.x + recycleOffset < Runner.distanceTraveled) {

Recycle(); } }

private void Recycle() {

Vector3 scale = new Vector3(

Random.Range(minSize.x, maxSize.x), Random.Range(minSize.y, maxSize.y), Random.Range(minSize.z, maxSize.z)); Vector3 position = nextPosition; position.x += scale.x * 0.5f; position.y += scale.y * 0.5f;

Transform o = objectQueue.Dequeue(); o.localScale = scale;

o.localPosition = position; nextPosition.x += scale.x; objectQueue.Enqueue(o);

nextPosition += new Vector3(

Random.Range(minGap.x, maxGap.x) + scale.x, Random.Range(minGap.y, maxGap.y), Random.Range(minGap.z, maxGap.z)); if (nextPosition.y < minY) {

nextPosition.y = minY + maxGap.y; }

else if (nextPosition.y > maxY) {

nextPosition.y = maxY - maxGap.y; } }}

然后就要创建⼀个⽤于显⽰平台的形状了,在Skyline⽂件夹⾥,选中Skyline Close Mat ,Ctrl+D复制⼀份,颜⾊改为(255,60,255)然后拖放到Platform⾥,

改名为Platform Regular Mat, 然后创建⼀个Cube,把这个Meterial 拖放到Cube上,然后把Cube拖回到Platform⽂件夹⾥,使之成为预设,改名为Platform

在层次视图⾥创建⼀个 Empty GameObject,命名为Platform Manager, 同样也放到Managers 下⾯,成为它的⼦对象。把Platform Manager这个脚本拖放到对象上,成为它的

组件。参考下图设置⼀下脚本的各个变量的值。

现在有平台了,是时候升级⼀下我们的“奔跑者”了,我们使⽤物理引擎来实现跑,跳,坠落等效果。选中在层次视图⾥选中“奔跑者”,然后Compnent->physics->rigid body,

给它添加物理引擎⽀持,因为我们不想让它旋转也不想跳出我们的视野,因此要给他添加 Z轴约束并且锁定所有的旋转⽅向。因为运动将会在平台上平滑的移动来完成,让我们来创建⼀个没有摩擦的材质(Project 视图上 Platform⽂件夹上 Create->PhysicsMaterial)。 具体设置如下图所⽰。

将这个物理材质设置为层次试图⾥的 Runner的 Box Collider 组件的 Material 属性

把Runner的Position 设置为(0,2,0)这样的话 ⼀开始 “跑步者” 就会降落在平台上,然后开始运动。

运⾏⼀下,可以看到“跑步者”落到平台,然后向右侧运动,跟设想的⼀模⼀样,但是假如它蹭到平台的边缘,就会发现运动有些奇怪。这是因为即使在这个情况下,Update也不会不断修改奔跑者”位置的,让我们换⼀种⽅式,使⽤物理引擎,采⽤添加“⼒”来使物体位置改变。把Runner.cs代码修改如下:

public class Runner : MonoBehaviour { public static float distanceTraveled; public float acceleration; private bool touchingPlatform;

void Update() {

distanceTraveled = transform.localPosition.x; }

void FixedUpdate() {

     //碰撞的时候不会继续作⽤⼒ if (touchingPlatform) {

rigidbody.AddForce(acceleration, 0f, 0f, ForceMode.Acceleration); } }

void OnCollisionEnter() {

touchingPlatform = true; }

void OnCollisionExit() {

touchingPlatform = false; }}

设置acceleration的值为5

在Platform⽂件夹⾥,像刚才那样给Platform也创建物理材质,命名为 Platform Regular PMat, 设置如下,然后把它复制给Platform的预设(prefab)

现在平台有了⼀些摩擦⼒,但是因为有持续作⽤⼒,所以我们的“跑步者”能够克服这些阻⼒。下⾯再给Runner.cs 添加⼀个变量来控制“跑步者”的跳跃速度。

添加变量 jumpVeclocity 设置为 (1,7,0)将 Runner.cs 代码改为如下:

public class Runner : MonoBehaviour { public static float distanceTraveled; public Vector3 jumpVelocity;

public float acceleration; private bool touchingPlatform;

void Update() {

if (touchingPlatform && Input.GetKeyDown(KeyCode.A)) {

Debug.Log(1);

rigidbody.AddForce(jumpVelocity, ForceMode.VelocityChange); }

distanceTraveled = transform.localPosition.x; }

void FixedUpdate() {

if (touchingPlatform) {

rigidbody.AddForce(acceleration, 0f, 0f, ForceMode.Acceleration); } }

void OnCollisionEnter() {

touchingPlatform = true; }

void OnCollisionExit() {

touchingPlatform = false; }}

现在运⾏,然后按下⿏标左键,就可以让我们的“跑步者”跳跃了。

但是玩⼀会就发现,假如“奔跑者”碰到平台的边缘,我们可以通过不断的按⿏标左键来防⽌坠落。这是⼀个bug,需要修复⼀下。

解决⽅案很简单,⼀旦玩家按下⿏标左键,就将touchingPlatform变量的值设为false,就不可以连续的跳跃了。

void Update() {

if (touchingPlatform && Input.GetKeyDown(KeyCode.A)) {

touchingPlatform = false;

rigidbody.AddForce(jumpVelocity, ForceMode.VelocityChange); }

distanceTraveled = transform.localPosition.x; }

因为Unity的跨平台做的实在是太好了,我们只需要简单两步就可以⽣成Windows Phone的⼯程,在菜单栏 File-> Build Setting弹出对话框然后选择 Player Setting

修改⼀下 Orientation ,连上你的WP8⼿机,然后点击 Build & Run ,会弹出⼀个选择⽂件夹的对话框,因为Unity会帮我们⽣成⼯程,所以这也就是⼯程的所在地,

新建⽂件夹 Projects->WP8 然后选择,等待⼀会编译完成,会发现游戏开始了,很兴奋吧!这么简单就可以做⼀款游戏,so easy, ⽼板再也不担⼼项⽬进度了。但是

还有问题,因为没有处理回退事件,所以现在的游戏是⽆法通过后退按钮退出的,找到编译出来的项⽬⼯程,打开,然后注释后退事件的代码:

private void PhoneApplicationPage_BackKeyPress(object sender, CancelEventArgs e){

//e.Cancel = UnityApp.BackButtonPressed();}

OK,⾄此,第⼀部分项⽬完成了,请等待 后续 的到来。附项⽬下载地址:

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- haog.cn 版权所有 赣ICP备2024042798号-2

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务