装饰世界
如果你已经下载了之前的素材包,那么在这里可以找到一些素材,比如说箱子。
现在当我们运行游戏的时候,可以发现人物总是在箱子的前方或者后面并且不会触碰到该物体,而是直接穿过。
让我们仔细思考一下,为了更加真实,应该人物站在物体前面就是人物的图层在上面,而人物在物体的后面应该是物体的图层在上面,说明是要根据角色的方位改变图层的状态。
屏幕上位置较低的游戏对象(y坐标较小)应在屏幕位置较高的游戏对象(y坐标)之后显示。
更改图形设置
现在要指示Unity根据游戏对象的y坐标来绘制游戏对象。
- 选择Edit -> Project Settings
- 在左侧类别菜单中,单击Graphics。
- 在 Camera Settings 中,找到 Transparency Sort Mode 字段。此字段决定了精灵的绘制顺序。使用下拉菜单将此设置从 Default 更改为 Custom Axis。
- 在 Transparency Sort Axis 中添加以下坐标:x = 0 ; y = 1; z = 0
这个时候就可以看到当人物比箱子高的时候,人物将会在箱子后面,而人物比箱子低的时候,人物会在箱子前面,但是变化还是有些奇怪,需要再改进一下。
调整精灵设置
要更加细致的改进需要设置一下Sprite Renderer。
- 在Hierarchy中,选择人物对象。
- 在Inspector中,找到Sprite Renderer组件。
- 找到Sprite Sort Point 字段。目前,这个字段是Center,意味着会使用人物的中心点来决定是否在前面还是后面绘制,我们将Sprite Sort Point更改为Pivot
调整轴心
轴心是你可以手动定义的特殊点,充当精灵的“锚点”。如果你旋转精灵,精灵将围绕这个点旋转。这个点也是用于放置精灵的点。这意味着,如果游戏对象位于 (0,0),并且将 Pivot 设置为角色的头部,则会在 (0,0) 绘制头部。如果轴心在双脚上,则会在 (0,0) 绘制双脚
- 在Project窗口中,选择Assets -> Art -> Sprites。选择人物
- 在 Inspector 中,单击 Sprite Editor 按钮。此时将打开你在先前教程中使用的 Sprite Editor
- 单击图像以显示精灵边框。你应该会在中心看到一个小的蓝色圆圈。这是轴心的当前位置,可以将蓝圈拖到所需的位置。或者在Pivot下拉框选择Center。
- 将Custom Pivot 设置为 X = 0.5; Y = 0。
- 单击Apply进行应用。
预制件
这里的预制件是将Hierarchy中的物品拖到Project窗口中,就会自动生成预制件,以此达到在场景中复用的技巧。
而修改预制件,我们可以在Hierarchy看来拉进来的游戏对象变成的蓝色,旁边有一个小箭头,这个时候这些游戏对象都来自于预制件,点击小箭头进行修改就能改动所有的预制件。
世界交互 - 阻止移动
在此我们正式开始学习物理系统啦!
物理系统就是模拟物体的碰撞和作用力,需要使用所有数学公式来计算对象上的接触和力,不过Unity是自带物理系统的,当物体含有Rigidbody 2D的组件会进行这些计算。
添加Rigidbody 2D组件
- 进入人物的预制件模式。
- 在Inspector中,单击Add Component 按钮
- 搜索Rigidbody 2D,选择该组件
这个时候当我们启动游戏的时候,我们的角色会掉下去,可能的原因是人物有重力系统, 这样导致y轴向下是作用力的方向。
现在我们需要禁用人物的重力,请注意:一定要在预制件模式中修改,不然只是修改单个人物!!!
如果你不小心这么做了,我们有另一种方法,首先我们将错就错,直接单击人物,找到Inspector中,在Rigidbody 2D组件中有一个Gravity Scale属性将其设置为0.
我们接下来将这个设置好的单个人物覆盖整个预制件,在Inspector中,查看人物标题,单击Overrides下拉菜单,单击Apply All将此更改应用于所有预制件中。
好的,人物有了物理系统,还需要一个碰撞体,以告诉系统哪个对象是实体部分
添加碰撞体
- 打开人物预制件模式,在Inspector中,单击Add Component
- 搜索Box Collider 2D,然后添加此组件。
- 现在在Scene视图中会看到人物有绿色的线,这个就是碰撞体的形状。
- 让我们为箱子也添加相同的组件。
在此我们简单做了这样操作,不过发现物体有以下几个问题:
- 人物会左右旋转晃动
- 人物和箱子碰撞的时候会发生抖动
- 人物和箱子有一定距离的时候就已经开始碰撞了
解决旋转问题
- 人物在预设模式下打开
- 在Inspector中,找到Rigidbody 2D组件
- 单击Constrants旁边的小箭头展开
- 启用Freeze Rotation 复选框以保证刚体不会有任何旋转
解决抖动问题
在解决问题之前要思考为什么会出现这种问题,这里就要说道物理系统是如何计算碰撞的。当有刚体的物体移动的时候,在内部会有一个物理场景,在该物理场景只有简单的几何体,通过计算其中的碰撞和移动来计算物体的位置,计算完之后再返回到游戏场景之中
这样会导致一个事情,在物理场景还未传回来的时候,人物已经进入到碰撞体内部,当物理场景的位置传回来的时候会让人物拉到该位置,导致人物抖动。
要解决 人物的抖动问题,你需要移动刚体本身而不是游戏对象变换组件,并让物理系统将游戏对象位置同步到刚体位置。这样,物理系统就可以在进入箱子之前停止移动,而不必在 人物已经进入箱子之后再移动人物。
此时我们需要修改人物移动代码Ruby Controller:
public class RubyController : MonoBehaviour
{
Rigidbody2D rigidbody2d;
float horizontal;
float vertical;
// 在第一次帧更新之前调用 Start
void Start()
{
rigidbody2d = GetComponent<Rigidbody2D>();
}
// 每帧调用一次 Update
void Update()
{
horizontal = Input.GetAxis("Horizontal");
vertical = Input.GetAxis("Vertical");
}
void FixedUpdate()
{
Vector2 position = rigidbody2d.position;
position.x = position.x + 3.0f * horizontal * Time.deltaTime;
position.y = position.y + 3.0f * vertical * Time.deltaTime;
rigidbody2d.MovePosition(position);
}
}
- Rigidbody2D rigidbody2d; 此行代码将创建一个新变量(名为 rigidbody2d)来存储刚体并从脚本中的任何位置访问刚体。
- float horizontal; float vertical; 这两行代码将创建两个新变量来存储输入数据。这些变量曾在 Update 函数中声明过,但是由于你现在需要从另一个函数 (FixedUpdate) 访问这些变量,因此在此处又声明了这些变量。
rigidbody2d = GetComponent<Rigidbody2D>(); 此代码位于 Start 函数内,因此在游戏开始时仅执行一次。此代码要求 Unity 向你提供与脚本附加到同一游戏对象(即你的角色)上的 Rigidbody2D。
在 Update 函数中,你删除了与移动相关的所有代码。你保留了用于读取输入的代码,这次是位于先前声明的两个变量中。
Vector2 position = rigidbody2d.position; 在 FixedUpdate 函数中,你添加了曾位于 Update 函数中的代码行,并调整了此代码以使用刚体位置。
rigidbody2d.MovePosition(position); 同样,你现在使用刚体位置,而不是使用 transform.position = position; 来设置新位置。这行代码会将刚体移动到你想要的位置,但是如果刚体在移动中与另一个碰撞体碰撞,则会中途停止刚体。
调整碰撞体的大小
之前说过物理场景中只是简单的几何体,而我们之前也见过那个绿色的线,那就是碰撞的几何体,所以我们需要调整一下大小让碰撞看起来更加合理。
- 双击箱子的预制件,在Inspector中,找到Box Collider组件,单击Edit Collider按钮,调整碰撞体的大小。
- 为人物也同样设置碰撞体的大小。
在这里,我们需要说明调整大小要符合实际情况,由于是2D游戏,所以我们需要思考的是如何让这些物体移动更加真实。
添加瓦片地图的碰撞
现在需要对场景中不可以穿过的物体进行设置碰撞,如水面。
- 在Hierarchy中,选择Tilemap游戏对象
- 在Inspector中,单击Add Component按钮
- 搜索Tilemap Collider 2D,选择它,你会在Scene视图中为所有瓦片添加绿色碰撞块
- 在Project窗口中,找到TIle文件,选择所有不是水的瓦片,取消碰撞块。
- 在Inspector中,找到Collider Type属性,然后将该属性从Sprite改为None。
- 再添加一个组件为Composite Collider 2D,这时他将自动添加Rigidbody 2D组件,启动Used By Composite复选框
- 在Rigidbody 2D组件中将Rigidbody Body Type属性设置为Static。这个属性将让刚体无法移动从而提升优化。
目前我们已经接触到了物理系统,那么接下来我们是否可以自己完成一些简单游戏和想法呢?