1 前言
英雄的宝剑并非只是装饰物,利剑出鞘时可以对怪物造成伤害。同样,怪物挥出铁拳时也会对英雄造成伤害。当然,都有同样的前提:在武器碰到对方的情况下,才会造成伤害。利用物理引擎,可以轻松的实现碰撞检测
2 添加怪物
场景中目前只有英雄,需要增加一些陪练对象,在场景中添加怪物:
-
在石头人场景中挑一只喜欢的复制到游戏场景
-
同英雄一样,为怪物对象创建父对象,命名为 Enemy。宝剑和怪物可以产生碰撞,所以需要挂载胶囊碰撞器,并调整参数以适应怪物的形体
调整 Enemy 的位置及旋转
调整模型的缩放
3 设置 Layer
Layer 定义哪些游戏对象可以与不同的功能以及彼此交互。它们主要有两种用途:由摄像机用来仅渲染场景的某一部分;由光源用来仅照亮场景的某些部分。但是,层也可以供射线投射用于选择性地忽略碰撞体或创建碰撞。更多信息请参阅文档:https://docs.unity3d.com/cn/2021.2/Manual/Layers.html
1 添加 Layer
之前增加了 Environment 和 Player 层,怪物和英雄也需要要产生碰撞,因此再增加一个 Enemy 层
2 分配 Layer
将怪物对象及其所有子对象分配到 Enemy 层
3 设置碰撞交互 Layer
在菜单中选择 Edit > Project Settings,然后选择 Physics 类别,勾选需要交互的 Layer
4 设置 Tag
标签 (Tag) 是可分配给一个或多个游戏对象的参考词。例如,可为玩家控制的角色定义 Player 标签,并为非玩家控制的角色定义 Enemy 标签。还可以使用 Collectable 标签定义玩家可在场景中收集的物品
标签有助于识别游戏对象以便于编写脚本。通过使用标签,不需要使用拖放方式手动将游戏对象添加到脚本的公开属性,因此可以节省在多个游戏对象中使用相同脚本代码的时间
标签对碰撞体控制脚本中的触发器很有用,例如:需要通过标签确定玩家是否与敌人、道具或可收集物进行交互。更多信息请参阅文档:https://docs.unity3d.com/cn/2021.2/Manual/Tags.html
点击 Tag 下拉菜单,点击 Add Tag...
在 Tags 中添加 Enemy(怪物) 和 Weapon(宝剑)
5 添加刚体及碰撞体
当两个对象碰撞时,可能会发生许多不同的脚本事件,具体取决于碰撞对象的刚体配置
以下图表详细列出了根据附加到对象的组件来调用的事件函数。某些组合仅会使两个对象之中的一个对象受到碰撞的影响,但一般规则是物理特性不会应用于没有附加刚体组件的对象
游戏中期望宝剑和怪物,双拳和英雄分别产生碰撞,按照图表的结论,需要为宝剑和怪物增加碰撞体,而且其中至少有一方需要有刚体,这里暂时将刚体添加到宝剑
在 Scene 中点击宝剑, Hierarchy 中依次展开英雄的模型子对象,定位到宝剑的预制体,添加刚体及盒型碰撞体,并调整参数以适应宝剑的形状
宝剑增加刚体只是为了碰撞检测,并不期望受重力影响,也不期望被物理引擎驱动,所以取消勾选 Use Gravity,以及勾选 Is Kinematic。 关于刚体属性的更多信息,请参阅文档:https://docs.unity3d.com/cn/2021.2/Manual/class-Rigidbody.html
英雄已经添加了刚体组件,所以怪物的铁拳只需要增加碰撞体。拳头是球形,因此添加球形碰撞器,调整参数以贴合双拳
当武器(宝剑、铁拳)碰到对方身体时,希望看到的是透体而过,而不是推着对方的身体后退,Unity 中碰撞体的 Is Trigger 可以实现该功能。勾选 Is Trigger 后,该碰撞体将用于触发事件,并被物理引擎忽略。即该碰撞体不会表现为实体对象,只会允许其他碰撞体穿过
6 脚本碰撞回调
发生碰撞时,物理引擎会在附加到相关对象的所有脚本上调用特定名称的函数。对象的碰撞体配置为触发器(即碰撞体只检测某物何时进入而不进行物理反应)时,将调用相应的 OnTriggerEnter、OnTriggerStay 和 OnTriggerExit 函数
游戏中期望英雄和怪物被攻击时都能有所反馈,所以需要在 PlayerController 和 Enemy 游戏对象上挂载填写了 OnTriggerEnter 函数的脚本
创建怪物脚本,挂载到怪物对象上
脚本中添加代码:
public void OnTriggerEnter(Collider other)
{
if (other.transform.CompareTag("Weapon"))
{
}
}
同样在 PlayerController 中添加碰撞回调
public void OnTriggerEnter(Collider other)
{
if (other.transform.CompareTag("Enemy"))
{
}
}
相比字符串的比较,CompareTag 方法可以更高效地检查 GameObject 的标签,该方法包括验证标签是否存在,不会导致任何内存分配