在Unity游戏开发过程中,经常会遇到各种碰撞检测的问题。本文将分享一个具体的案例,说明如何修复MeshCollider和BoxCollider在攻击动画中的问题。
在Unity中,为角色创建了一个健康系统,但在第19天的开发中,遇到了一个问题:尽管攻击动画播放了多次,但角色的碰撞器(Collider)似乎只能与敌人碰撞一次。
问题出现在在第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;
}
}
这个脚本的工作流程如下:
现在已经将碰撞代码从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);
}
}
}
代码中的更改如下: