Unity中修复游戏对象碰撞器的问题

Unity游戏开发过程中,经常会遇到各种碰撞检测的问题。本文将介绍如何修复Mesh Collider和Box Collider的问题,以确保游戏对象之间的正确交互。

Mesh Collider的问题

在第12天的开发中,为骑士创建了一个Mesh Collider。然而,发现一个问题:即使多次执行攻击动画,碰撞器也只会与敌人碰撞一次。

Mesh Collider不能跟随模型的动画,这意味着当骑士第一次接触时,网格可能会触碰到,但之后如果玩家没有被碰撞器推开,网格就再也不会触碰到了。

为了解决这个问题,需要对Mesh Collider进行一些修改。仍然需要Mesh Collider来防止穿过敌人。目前,面临的问题是可以穿过骑士,但现在会修复这个问题。

将在骑士的手上添加一个Box Collider。这样,就可以确保当玩家被击中时,能够检测到碰撞。

目前,不能移动网格,因为它在父体中。根据关于不正确网格定位的帖子,将创建一个新的空对象,并在那里添加网格碰撞器。

这对来说是有效的,因为只需要网格进行碰撞检测和射线投射射击。

首先,需要从knightprefab游戏对象中移除Mesh Collider。选择knightprefab,右键单击并选择Create Empty,以创建一个新的游戏对象。让将这个对象重命名为Collider。

选择Collider并添加一个新的Mesh Collider组件。对于Mesh,选择body以恢复骑士模型。

现在,不能只是走过骑士。

现在已经解决了Mesh Collider的问题,将修复最初的问题,即在敌人攻击时处理伤害。

为此,将在骑士的拳头上添加box collider。具体来说,在knightprefab->hips->spine->chest->L_shoulder/R_shoulder->一直到L_Wrist/R_Wrist。

对于每个box collider,将盒子的scale设置为0.25以适应手的大小。

现在已经这样做了,需要将一个脚本附加到手模型上,以便可以检测碰撞。父对象的脚本不能检测其子对象的碰撞。

同样重要的是,原来的脚本:EnemyAttack,仍然需要保留在原处,因为需要访问位于父对象中的animator组件。

为了解决问题,将从EnemyAttack移动碰撞部分的代码到一个新的脚本,名为FistCollider。

C# using UnityEngine; public class FistCollider : MonoBehaviour { private GameObject _player; private bool _collidedWithPlayer; void Start() { _player = GameObject.FindGameObjectWithTag("Player"); _collidedWithPlayer = false; } void OnCollisionEnter(Collision other) { if (other.gameObject == _player) { _collidedWithPlayer = true; } print("enter collided with _player"); } void OnCollisionExit(Collision other) { if (other.gameObject == _player) { _collidedWithPlayer = false; } print("exit collided with _player"); } public bool IsCollidingWithPlayer() { return _collidedWithPlayer; } }

代码的流程如下:

像EnemyAttack脚本一样,想要访问玩家游戏对象,并检查否与敌人发生了碰撞。

在Start()中,确保实例化了两个变量。

在OnCollisionEnter()和OnCollisionExit()中,如果与玩家发生了碰撞,那么将设置布尔标志。

在IsCollidingWithPlayer()中,将布尔_collidedWithPlayer提供给任何调用它的人。注意这个函数是public的,所以其他脚本可以访问这个。将在后面使用它。

让将脚本附加到L_Wrist和R_Wrist。

现在已经将碰撞代码的一部分从EnemyAttack移动到FistCollider,让在EnemyAttack中使用FistCollider。

C# using UnityEngine; public class EnemyAttack : MonoBehaviour { public FistCollider LeftFist; public FistCollider RightFist; private Animator _animator; private GameObject _player; void Awake() { _player = GameObject.FindGameObjectWithTag("Player"); _animator = GetComponent(); } void OnTriggerEnter(Collider other) { if (other.gameObject == _player) { _animator.SetBool("IsNearPlayer", true); } print("enter trigger with _player"); } void OnTriggerExit(Collider other) { if (other.gameObject == _player) { _animator.SetBool("IsNearPlayer", false); } print("exit trigger with _player"); } private void Attack() { if (LeftFist.IsCollidingWithPlayer() || RightFist.IsCollidingWithPlayer()) { _player.GetComponent().TakeDamage(10); } } }

代码中的更改如下:

首先,创建了新的public变量:LeftArm和RightArm,它们是刚刚创建的FistCollider脚本。

清理了很多代码,特别是碰撞部分以及与之相关的任何内容。

在Attack()中,使用新FistCollider进行与玩家的碰撞,然后当动画的攻击事件被触发时,检查玩家是否被击中。如果他们被击中(意味着骑士的拳头与玩家发生了碰撞),玩家将受到伤害。

现在脚本已经完成,最后需要做的是确保将FirstCollider对象附加到玩家上。

可以直接将游戏对象附加到位置,脚本将自动被选中。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485