欢迎来到第三部分。这一部分我们将设计一些可以让玩家碰撞之后与其交互的物体。在开始之前,我们打开 Scene 文件夹,然后双击开回 SampleScene 场景(记得先保存 Dungeon1 场景

我们需要创建一个名为 Collidable 的脚本(Script),这个脚本是放在非玩家单位(如NPC,可破坏物品)的,当玩家触碰到拥有 Collidable 脚本的物体时,将会触发某些设定好的行为。

在 Scripts 文件夹里右键点击 Create / C# Script 创建脚本,将其命名为 Collidable 然后打开文件。

编程

首先我们声明三个变量:

  1. ContractFilter2D 是 public 修饰符,意味着我们可以在 Unity 的 Inspector 面板中对其进行调整。它用于过滤需要检测的游戏物品。
  2. BoxCollider2D 用于获取当前游戏物体(也就是被挂上此脚本的物体)中的 BoxCollider2D。我们之后需要对这个 BoxCollider2D 进行操作。
  3. Collider2D 数组用于保存 BoxCollider2D 所碰撞到的所有物体。Collider2D 是所有碰撞体(如 BoxCollider2D、CircleCollider 2D 等)的父类。

我们用了 protected virtual 修饰符来修饰 Start 和 Update 函数,是因为这个类将会作为父类。也就是它会有儿子继承它。在 Start 函数里,我们首先获取了当前游戏物体的 BoxCollider2D。

然后在 Update 函数里,我们调用 BoxCollider2D 的 OverlapCollider 函数。该函数用于检测经过 ContactFilter2D 过滤之后的游戏物件,然后将碰撞到的物体保存在 Collider2D 数组里。

我们使用 for 循环遍历 Collider2D 数组,如果遍历到的元素为 null 则跳过该轮循环,否则就调用我们定义的 OnCollide 函数,传递当前碰撞的元素进去。最后手动清除 Collider2D 数组元素,将当前遍历到的元素设置为 null,以准备下一次循环使用。

我们定义了一个 OnCollide 函数,里面只写了一句 Debug.Log 函数。在这个章节,我们先将 Update 函数里传递进来的 Collider2D 对象名字输出出来。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Collidable : MonoBehaviour
{
public ContactFilter2D filter;
private BoxCollider2D boxCollider;
private Collider2D[] hits = new Collider2D[10]; // 检测所碰撞的物体,最大能检测 10 个

protected virtual void Start()
{
boxCollider = GetComponent<BoxCollider2D>();
}

protected virtual void Update()
{
// 碰撞
boxCollider.OverlapCollider(filter, hits); // 检测当前 GameObject 所碰撞到的物体,然后加入到 hits 数组里。
for (int i = 0; i < hits.Length; i++)
{
if(hits[i] == null)
{
continue;
}

OnCollide(hits[i]);

// 手动清除数组
hits[i] = null;
}
}

// 当被碰撞的时候被调用
protected virtual void OnCollide(Collider2D collider)
{
Debug.Log(collider.name);
}
}

将这段代码拖到 Test_NPC 上,然后开始游戏。当玩家接触到 NPC 时,Console 会输出玩家的名字

上面我们写了个 OnCollide 函数,这就是今天的重点。我们将用其他脚本继承 Collidable 脚本,然后重新实现这个 OnCollide 函数,因为 OnCollide 函数的调用时间在 Update 函数里。所以举个例子:

  1. 当我们在箱子的脚本中重写这个函数,则箱子就会有自己的行为
  2. 而当我们给 NPC 重写这个函数,NPC 也一样有自己的行为。

那么本章内容就到这里啦!喜欢我的文章的小伙伴可以点击 Discord 社交图标加入我们的服务器哦!