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

Unity游戏开发过程中,经常会遇到各种碰撞检测的问题。本文将分享一个具体的案例,说明如何修复MeshCollider和BoxCollider在攻击动画中的问题。

问题描述

在Unity中,为角色创建了一个健康系统,但在第19天的开发中,遇到了一个问题:尽管攻击动画播放了多次,但角色的碰撞器(Collider)似乎只能与敌人碰撞一次。

修复MeshCollider

问题出现在在第12天为骑士创建的MeshCollider上。MeshCollider不能跟随模型的动画,这意味着当骑士第一次攻击时,MeshCollider可能会与接触,但之后如果玩家没有被碰撞器推开,MeshCollider就不会再与接触。

为了解决这个问题,需要对MeshCollider进行一些修改。仍然需要MeshCollider来防止玩家穿过敌人。目前的问题是玩家可以穿过骑士,但会立即修复这个问题。

为了确保当玩家被骑士的拳头击中时能够受到伤害,将在骑士的拳头上添加BoxCollider。具体来说,在knightprefab的层级结构中,从hips到spine,再到chest,然后是L_shoulder/R_shoulder,一直到L_Wrist/R_Wrist。对于每个BoxCollider,将Box的scale设置为0.25,以适应手的大小。

为了解决碰撞问题,将创建一个新的脚本FistCollider,它将处理骑士拳头的碰撞,并将结果传递给EnemyAttack脚本。

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; } }

这个脚本的工作流程如下:

  • 在Start()方法中,初始化_player和_collidedWithPlayer变量。
  • 在OnCollisionEnter()和OnCollisionExit()方法中,如果碰撞的对象是玩家,设置布尔标志。
  • 在IsCollidingWithPlayer()方法中,将布尔变量_collidedWithPlayer提供给调用它的任何人。注意,这个函数是public的,所以其他脚本可以访问它。将在后面使用它。

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

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变量LeftFist和RightFist,它们是刚刚创建的FistCollider脚本。
  • 清理了很多代码,特别是与碰撞有关的代码。
  • 在Attack()方法中,使用新的FistCollider来检测与玩家的碰撞,然后当动画的攻击事件被触发时,检查玩家是否被击中。如果他们被击中(意味着骑士的拳头与玩家发生了碰撞),玩家将受到伤害。
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485