跑起来
到目前为止还没有什么效果,我们需要做些改变。首先通过实现Runner向右移动来创建一个实体模型的游戏。
创建一个新的C#脚本,在Runner文件夹中命名为Runner,并把它贴到Runner cube上。通过下面的代码让它移动起来。
1
2
3
4
5
6
7
8
|
using UnityEngine;
public class Runner : MonoBehaviour {
void Update () {
transform.Translate(5f * Time.deltaTime, 0f, 0f);
}
}
|
代码不是很多,但是已经显示出进入play模式时出现了一个问题。相机不能跟随cube。为了修复这个,把Main Camera拖拽到Runner上,这样就成为了它的子对象。
现在Runner停留在视图中固定的位置,可以看到近处的skyline cube比远离的cube移动地快。
设置移动相机
生成Skyline
现在已经有了基本的移动,接下来生成一排cube,来构建出一个无尽的skyline。首先要注意只有skyline的可见部分需要存在。一旦cube从屏幕的左侧掉落,它就可以被销毁。或者更好的是,它可以被重新用作构建即将进入视图的下一部分的skyline。我们可以设定此行为,通过生成cube的一个队列,不断地把不可见的前方cube移动到后方。
在Skyline文件夹创建一个C#脚本,命名为SkylineManager。我们将用它来创建两个管理器,其中一个用于每个Skyline层。至少,它需要知道用哪个预制来生成Skyline,所以先添加一个公共变量。
1
2
3
4
5
6
|
using UnityEngine;
public class SkylineManager : MonoBehaviour {
public Transform prefab;
}
|
为了使一切有条理,创建一个新的空对象(GameObject / Create Empty),命名为Managers,把它当做一个容器,来包含所有的管理器对象。再创建一个空对象,命名为Skyline Close Manager,把它变成Managers的子对象,并通过拖拽脚本为其创建一个SkylineManager 组件。
现在要把两个skyline cube变成预制,通过把它们拖拽到Skyline项目文件夹,或者通过Create / Prefab,然后拖拽到上面。然后,从Hierarchy删除两个cube。现在把Skyline Close预制拖拽到Skyline Close Manager的预制区域。
管理器和预制
我们需要一个起点来生成cube,所以要添加一个startPosition变量。还要决定生成多少cube才能填满屏幕,使用numberOfCubes变量来实现这一点。为了记录下一个cube在哪里生成,我们要用到nextPosition私有变量。
1
2
3
4
5
6
7
8
9
|
public Transform prefab;
public int numberOfObjects;
public Vector3 startPosition;
private Vector3 nextPosition;
void Start () {
nextPosition = startPosition;
}
|
下一步是生成cube的初始行。用一个简单的循环来实现它,实例化新对象,设置它们的位置,通过对象的宽度来推进nextPosition,这样它们就能形成连绵不绝的线。由于我们用的是单位cube,它们的宽度就等于它们的localScale.x。
1
2
3
4
5
6
7
8
|
void Start () {
nextPosition = startPosition;
for (int i = 0; i < numberOfObjects; i++) {
Transform o = (Transform)Instantiate(prefab);
o.localPosition = nextPosition;
nextPosition.x += o.localScale.x;
}
}
|
设置Start Position 为(0, -1, 0) ,把Number of Objects设置为10,将能看到Runner下方出现了一排cube。然而,一但cube移动出视图,就再也看不到它们了。
实例化skyline.
我的想法是一旦Runner离开cube一段距离,就循环cube对象。为了实现它,管理器必须知道Runner走了多远。通过添加数据变量distanceTraveled到Runner来实现,并且要确保数据一直是新的。
1
2
3
4
5
6
7
8
9
10
11
|
using UnityEngine;
public class Runner : MonoBehaviour {
public static float distanceTraveled;
void Update () {
transform.Translate(5f * Time.deltaTime, 0f, 0f);
distanceTraveled = transform.localPosition.x;
}
}
|
把skyline对象存储在一个队列中,保持检查第一个对象是否应该被循环。如果是,就重置它,把它移动到队列的后方。使用recycleOffset变量来配置距离Runner多远时发生重用。我们把它设置为10。
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
|
using UnityEngine;
using System.Collections.Generic;
public class SkylineManager : MonoBehaviour {
public Transform prefab;
public int numberOfObjects;
public float recycleOffset;
public Vector3 startPosition;
private Vector3 nextPosition;
private Queue<Transform> objectQueue;
void Start () {
objectQueue = new Queue<Transform>(numberOfObjects);
nextPosition = startPosition;
for (int i = 0; i < numberOfObjects; i++) {
Transform o = (Transform)Instantiate(prefab);
o.localPosition = nextPosition;
nextPosition.x += o.localScale.x;
objectQueue.Enqueue(o);
}
}
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);
}
}
}
|
循环skyline 的配置
这样就能实现了。进入play模式后,就能看到cube重置自己的位置。然而,现在看起来还不太像skyline(天际线),为了让它看起来更像真实不规则的天际线,让我们随机缩放cube,无论是放置或是循环的时候。
首先,考虑到初始的放置和后来的循环cube基本上是在做相同的事情。把这段代码方法放到它自己的Recycle方法中,并重写Start 和 Update方法,用到它。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
void Start () {
objectQueue = new Queue<Transform>(numberOfObjects);
for (int i = 0; i < numberOfObjects; i++) {
objectQueue.Enqueue((Transform)Instantiate(prefab));
}
nextPosition = startPosition;
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);
}
|
接下来,我将介绍两个变量来配置允许的最大值和最小值,并使用它随机的决定对象的大小。决定大小之后,要确保对象的位置,使它们都对准底部。通过缩小一半尺寸来抵消,因为对象是围绕它们自己的位置的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public Vector3 minSize, maxSize;
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);
}
|
为了让skyline的效果好一点,设置
- Start Position为(-60, -60, 50)
- Min Size 为 (10, 20, 10)
- Max Size 为 (30, 60, 10)
- Recycle Offset 为60。
接下来添加第二个skyline层。复制Skyline Close Manager,把名字改成Skyline Far Away Manager。把它的预制改为Skyline Far Away 预制。设置
- Start Position 为 (-100, -100, 100)
- Recycle Offset 为 75
- Min Size 为 (10, 50, 10)
- Max Size 为(30, 100, 10)
当然你也可以使用你喜欢的任何值。
完整的skyline.
原文链接:http://catlikecoding.com/unity/tutorials/runner/
建议使用电驴(eMule)下载分享的资源。
说明:本教程来源互联网或网友分享或出版商宣传分享,仅为学习研究或媒体推广,wanshiok.com不保证资料的完整性。
|