12-创建场景:马路
你好,我是悦创。
到这里,你的三个场景块,做好了吗?做好了,我要继续开始做我们的马路了。

1. 进入场景编辑界面
双击我们的预制体就可以进入我们的场景编辑页面,进入之后就可以进行修改了。我们所有的修改,都会影响我们的所有用到这个预制体的场景。

2. 所存在的问题
我们要点击场景中的小花,但是经常不能一次性点击到,反而会点到我们的 Panel:「因为,有一层 UI 挡在我的画面上,我会经常不小心点到它」

当我把鼠标移到我们 Hierarchy 窗口时,在我们的 Panel 时,它会显示两个标记:

- 眼睛:代表物体是否在我们的场景中,可以看得见;
- 手:手的意思,代表我们的物体,是否可以在我们的场景中被点按;
所以,我们可以把整个 Canvas 设置为不能点按:

现在,我们就可以在我们的场景中随意点击我们的物体了,这样是不是很方便呢~
那接下来,我们要做游戏中最重要的部分了:公路。
3. 制作马路
这里我将带你做一个小汽车和公路的搭建。
3.1 修改锚点



接下来,找到公路的素材:



添加路边:



那么,在我们的公路上是不需要碰撞体的,所以我们也可以把公路变成一个模块。




接下来,要做我们的小汽车了。
3.2 制作小汽车




我们是双向车道,汽车是双方向移动,我们先做第一种情况:怎么让汽车🚗自然的移动起来。

还记得么,调整到和影子差不多大小即可:
- 设置 Trigger

所以,小青蛙跳到这个汽车位置的话,就判断它失误了。
因为,我们觉得,汽车是你青蛙跳不过去的。所以,青蛙在空中就被车撞了,因为车比较高。
我们也为它创建一个单独的标签:Car





我们还有动画,我们就要添加 Animator:








为什么要把采样率设为 20?

因为,我们一共有 20 张图片,所以希望一秒 20 帧。

点击运行我们看看:

可以看见小汽车🚗轮子在运行。
接下来,我们要实现小汽车的真实移动。
不过,我们想象一下:我们车要移动,我们在水上的木板也是会移动的。而且,它们的方式是一样的,我希望在左侧,会在一些固定的间隔里面,生成不同的汽车。「因为,我们有三种汽车」
所以,汽车需要有随机性。每次生成起来之后,小汽车只要向前跑就行,不用追着我们青蛙跑。木板也是,每次生成向前移动。
接下来,我们写一个通用的方法,来是我们的角色向前移动。「目前来看,向前移动就是向右移动」
4. 编写移动代码
4.1 新建代码文件夹


4.1 初步代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveForward : MonoBehaviour
{
// 首先我们需要三种小汽车有不同的速度
public float speed; // 方便我们在界面操作设置速度
// void Start()
// {
// }
// Update is called once per frame
void Update()
{
// 在这里我们调用函数
Move();
}
// 我希望我的小汽车不断的运行移动,我们来写一个方法
private void Move() {
// 我们想想,小汽车要怎么移动呢?
// 所谓的速度,它需要不断的在 update 里面去调用,使每一帧都向前前进一些,那前进的就是 speed
// 也就是我在我当前坐标的基础之上,让它 x 的方向,不断的添加的 speed
// 我们使用 transform,transform.position = transform.position + transform.right 和下面等价
transform.position += transform.right * speed * Time.deltaTime; // transform.right 当前角色的纵坐标的向右方向,我们要在这个基础之上乘以 speed,
// 接着我们乘以我们的时间修正,因为,我们之前说过 Update 是每帧执行,但是在不同设备上有不同的帧数,所以在这里我们会乘以一个时间修正。这个是固定写法 Time.deltaTime
// 相当于我们角色的方向,向右的意思
}
}
4.3 设置小汽车速度



保存项目,运行:

4.4 添加游戏失败条件
我们小青蛙碰除了碰到 Border 以外,或者你碰到了我们的小汽车,也应该会 Game Over。
所以,我们需要在代码文件 PlayerController.cs 中添加判断条件:
private void OnTriggerStay2D(Collider2D other)
{
if (other.CompareTag("Border") || other.CompareTag("Car")) // 比较标签// 这样我们就实现了,只要碰到其中一个游戏就 GameOver
{
Debug.Log("Game Over!");
}
if (!isJump && other.CompareTag("Obstacle"))
{
Debug.Log("Game Over! Obstacle");
}
}
5. 把我们的小汽车做成预制体

- 记得新建文件夹 Cars
- 拖拽进去即可
- 删掉现在汽车角色
我们到时候会怎么使用呢?
我们会在马路的两条车道上,放置生成汽车的点,它们会在这两个点生成出来。生成出来之后就直接开始移动了。
我们来测试一下:
- 先运行游戏
- 拖拽小汽车

不用管我们左侧界面是怎么样的,我们将小汽车拖拽到场景中,然后汽车会一直走。
我们思考一下:如果我们每隔一段时间生成小汽车,它都不断的这么走,那游戏玩了一段时间后,我们的场景中就会生成非常多的汽车。
所以,我希望我们的汽车移动出去一段距离之后,就把汽车销毁掉,不让它继续出现。其实木板也是同样的原理,所以我们来编写代码。
6. 连续的小汽车
void Update() // 持续每帧在运行的,在运行的过程当中我要判断它的坐标
// 就是在小汽车移动的初始坐标基础上,小汽车移动的 x 的差值超过了我们的范围,比如我们指定了一个宽度。
// 那么我们就销毁,所以我需要知道我们小汽车初始位置。
// 因为随着我们的场景不断的更新,不断的添加,它生成的坐标 x 和 y 不是固定的。
{
// 在这里我们调用函数
Move();
}
private Vector2 startPos; // 用于记录我们初始坐标的位置
// 在什么时候开始记录呢?
// 在我们 Start 的时候记录
private void Start()
{
startPos = transform.position; // 这样我们就拥有了初始坐标了
}
void Update()
{
// 接下来,我们需要在 Update 中判断一下:
if (Mathf.Abs(transform.position.x - startPos.x) > 25)
{
Destroy(this.gameObject); // 把当前的 gameObject 进行销毁 // Destroy 固定函数,移除场景中的 gameObject
}
// 在这里我们调用函数
Move();
}
进行测试:

这个 25,具体大小按你自己的需要来修改即可。
设为比较大的数值也是比较稳妥的方法。
7. 作业
三个汽车都做好。
- 修改锚点位置 Custom 0.5、0.2
- 创建动画
- 添加碰撞体
- 设置标签
- 绑定 MoveForward 的方法
- 每个小汽车可以设置不同的速度,比如2.1、2.5、2.8都可以,根据自己的想象设置速度
- 最后测试自己的小汽车
8. 寻找生成点
下一节,我们来学习如何随机生成我们的小汽车。
先拖拽一个小汽车到我们的 Road 当中

键盘的 F 键可以帮助我们快速锁定它的位置。

如果觉得小汽车的高度没有问题的话,我们就适当的向左移动。

比如说通常在下面那个位置,不会穿帮:

如果你往前生成就有可能会出现闪现的小汽车,所以至少要在场景之外。
所以我们要记住这个位置:

我希望在这个位置创建一个空的 GameObject,我可以鼠标右键创建 GameObject:

把我们创建的 GameObject 拖到和小汽车同级,你会发现和我们的小汽车的坐标依然是在同一个位置。


SpawnPoint A
第一个生成点




不管它有什么物体在上面都会有颜色。
9. 测试
清空小汽车预制体的坐标:

这样,在我们后面拖拽的时候就会到我们提前定好的生成点。

欢迎关注我公众号:AI悦创,有更多更好玩的等你发现!
公众号:AI悦创【二维码】

AI悦创·编程一对一
AI悦创·推出辅导班啦,包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Linux、Web全栈」,全部都是一对一教学:一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然,还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线,随时响应!微信:Jiabcdefh
C++ 信息奥赛题解,长期更新!长期招收一对一中小学信息奥赛集训,莆田、厦门地区有机会线下上门,其他地区线上。微信:Jiabcdefh
方法一:QQ
方法二:微信:Jiabcdefh
