使用磁贴图实现命中检测

更新页 :
页面创建日期 :

验证环境

窗户
  • 视窗 11
统一编辑器
  • 2021.3.3f1
输入系统包
  • 1.3.0

此提示的先决条件

作为此提示描述的前提,已预先进行了以下设置。

此提示的先决条件是什么?

关于借用地图材质

我们处理从以下网站借来的。

行走字符的实现

首先,实现一个地图和一个执行命中检测的角色。 可以使用键盘上的光标键移动此字符。 但是,如果实施正确的步行,它将与书本技巧的精髓相去甚远,所以这次我只移动一个简单的单图。

如果要实现步行动画,请参阅以下提示:

创建项目后,添加要移动到项目的对象的精灵图像。

选择图像,然后从检查器中将每单位像素数设定为 32。 这是因为地图芯片的一个正方形的大小是 32 像素,所以它适合这个。 配置完成后,单击下面的“应用”按钮。

将角色放在视图中。

创建一个脚本来移动精灵。 这类似于以下提示:

将脚本名称 Player 保留为 。

代码如下:

using UnityEngine;
using UnityEngine.InputSystem;

public class Player : MonoBehaviour
{
  // 一定時間ごとに呼ばれます
  void FixedUpdate()
  {
    // キーボードの情報を取得
    var keyboard = Keyboard.current;

    // スプライトの移動処理
    if (keyboard.leftArrowKey.isPressed)
    {
      transform.Translate(-0.1f, 0, 0, Space.World);
    }
    if (keyboard.rightArrowKey.isPressed)
    {
      transform.Translate(0.1f, 0, 0, Space.World);
    }
    if (keyboard.upArrowKey.isPressed)
    {
      transform.Translate(0, 0.1f, 0, Space.World);
    }
    if (keyboard.downArrowKey.isPressed)
    {
      transform.Translate(0, -0.1f, 0, Space.World);
    }
  }
}

附加到要移动的精灵。

运行游戏并检查是否要用键盘移动它。

准备地图提示

首先,我们将准备一个地图芯片并创建一个地图。 此过程类似于以下提示: 带有 2D Tilemap Extras 的 MapTips 也能够进行碰撞检测,但本文不会使用它们,因为该过程会很长。

准备地图提示的原始图像并将其添加到您的项目中。 为使操作更易于理解,请为地图芯片材料准备一个“步行场所”和一个“不可步行的地方”。

在检查器中为MapChips设置它,然后单击“应用”按钮。 配置完成后,打开精灵编辑器。

这是一个 32 像素的地图提示,所以我会在 32 像素处拆分它。

选择“磁贴调色板”选项卡。 如果没有,请使用菜单中的“窗口> 2D -> 平铺调色板”显示它。 创建新调色板。 这个名字是任意的,但现在我们称之为“MapChipPalette”。

在场景中创建一个 MapChipPalette 文件夹并指定它。

通过将地图提示拖动到调色板来添加地图提示。 将其保存在您之前创建的 MapChipPalette 文件夹中。

创建地图

这一次,地图命中判断将以“瓦片地图”为单位进行。 因此,我们将创建两个瓦片映射,“没有命中检测的瓦片地图”和“带命中检测的瓦片地图”。

首先,在层次结构中创建两个图块映射。 您可以在网格中创建两个。 为清楚起见,名称为“TilemapObeject”和“TilemapGround”。

首先,创建一个“TilemapGround”。 由于它是一个可移动的范围,您可以简单地铺设地面。 如果是在地面上,您可以更改模式。

顺便说一下,如果字符是隐藏的,请选择字符对象并将检查器的图层顺序 Sprite Renderer 设置为 2。 默认情况下,图层的顺序为 0,切片地图为 0,因此如果将其增加到此值以上,它将显示在前台。

然后选择“磁贴地图对象”并放置要使其静止的地图提示。 首先将图层顺序设置为 1。 这是为了让它出现在地面前面。

这就是你隐藏地面的样子。

当然,此时没有与碰撞检测相关的设置,因此您可以正常骑在高地上。 在此之后,我们将设置碰撞检测。

碰撞检测设置

首先,让我们设置角色。 此设置与下面的提示几乎相同,因此我将跳过详细信息并简要说明该过程。

从层次结构中选择一个角色对象,然后从添加组件中选择物理 2D -> 圆形碰撞体 2D。 如果物体的形状是矩形的,则“Box Collider 2D”就可以了。

同样,添加“物理 2D -> 刚体 2D”。

将重力刻度设置为 0 以防止 Rigidbody 2D 自动下落。

选中约束下的 Z 以防止角色在碰撞时旋转。

接下来,选择要点击的“TilemapObject”,然后从“添加组件”中选择“Tilemap -> Tilemap Collider 2D”。

仅此而已。 你甚至不需要任何编程。 运行游戏并尝试击中成为墙壁的物体。 我认为您可以确保它正确停止。

但是,当您真正击中它时,我认为行为中会有关注点。 以下是一些解决方案:

使用地图和解决方案进行命中检测的不便行为

当你碰壁时,你可能会发现一些困扰你的事情。

如果你靠墙移动,你会被夹在中间

Box Collider 2D 我认为如果您使用对象,就会发生这种情况。

例如,从下面的场景中,当您按下左下角的键时,您希望它沿着墙壁向左移动。 但是,在取得一些进展之后,我认为它会卡在某物上并停止。

按位置识别墙壁上的凹痕

Circle Collider 2D 我认为如果您附上. 墙应该是平坦的,但是如果你把它靠在墙上,你会看到墙在移动,就好像它是不平坦的。

障碍和颠簸的原因和解决方案

发生这种情况的原因似乎是“命中确定是在地图芯片的基础上执行的”。 实际上,当您选择TilemapObject时,命中检测所在的位置会出现一条绿线,您可以看到这是以MapTip单位绘制的一条线。

因此,如果移动物体在一条正好相当于一个地图芯片的线上,它将被判断为用一个地图芯片击中。 如果在地图芯片的边界处碰撞,两个地图芯片会被击中并判断,因此反弹的强度会增加。

我认为解决此问题的最佳方法是将命中检测与附加的地图芯片相结合。 具体操作方法如下:

从检查器中选择Tilemap Collider 2D 具有命中检测的“TilemapObject”,然后从 中选中“在复合中使用”。

如警告中所述,仅此一项不起作用,因此请从“添加组件”中选择“物理 2D -> 复合碰撞体 2D”。

刚体 2D 与复合碰撞体 2D 一起添加。

这有点令人困惑,但我认为您可以确认具有命中检测的地图芯片之间边界处的绿线已经消失。

我不希望磁贴移动,所以我将 Rigidbody 2D 组件正文类型保留为“静态”。

现在运行游戏并尝试让它移动。 我认为即使您沿墙壁对角线移动,它也不会被卡住,并且可以平稳移动而不会颠簸移动。

消除角色从墙上推回

你可以看到,如果你移动角色来推动墙壁,然后停止移动,它会表现得有点像从墙上反弹回来。

要解决此问题,Rigidbody 2D 请选择字符对象并从组件中将“碰撞检测”更改为“连续”。

“不连续”和“连续”的区别如下。

不连续的

碰撞检测是一种在移动后思考的机制。 它是一种从移动并嵌入墙壁的状态执行碰撞检测的形式。 如果将其与蹦床和橡胶联系起来很容易理解,但是嵌入的越多,力就会越强,反弹力也会越强。 相反,计算是在移动后进行的,因此处理成本低。

连续的

它在确定途中的内容时进行处理。 确定移动前后的位置之间是否有墙, 如果有一堵墙,它会判断那里的碰撞并停止,所以几乎没有排斥力。 相反,处理成本略有增加,因为计算包含在运动的中间。

被捕获在地图对象的一角

根据程序和位置的不同,有些被捕获,有些没有,原因没有太大变化。 顺便说一下,它发生在像 Box Collider 2D 这样的角上,而不是圆圈。

即使发生这种神秘现象,对撞机的圆角也很好,以避免障碍。 它仅限于 Box Collider 2D,但要使其变圆,角色对象的 Box Collider 2D 组件具有“边缘半径”,您可以在其中放置一个值。 如果输入 1 作为数字单位,则将对对象大小进行舍入。 这取决于大小,但最好放大约 0.1。

顺便说一下,命中判断仅根据圆度的大小增加,因此如果很大,请进行调整。 Box Collider 2D 有一个 Collider Edit 按钮,允许您通过单击该按钮直接在视图中调整其大小。 由于外绿线是实际的命中检测,因此请设置大小,使其不会不自然。

之后,运行游戏以确保它不会被划伤并进行调整。