기획자님이 요구하신
근접형 기본 몬스터의 공격 설정은 위와 같다. 처음에는 간단하다고 생각했다. 플레이어 기본 근접 공격에서 조금만 수정하면 될 줄 알았는데 아니었다. 근접형 기본 몬스터는 현재 두 가지 자식 오브젝트를 가진다. TargetArea는 SphereCollider가 연결되어 있고 추적 범위를 결정 짓는다.
BasicAttack도 SphereCollider가 연결되어 있고 공격 범위를 결정 짓는다. 물론 플레이어도 비슷한 방식으로 Weapon_1 자식 오브젝트를 가지고 SphereCollider를 가지고 있다. 몬스터 근접 공격에 대해 순서대로 설명하자면 최우선으로 SphereCollider 트리거가 호출이 되면 target이 범위안에 있는지 판별하는 함수인 FindVisibleTargets() 가 호출된다. 여기서 생기는 문제는 트리거 엔터는 범위안에 있을 때 한 번만 호출된다는 것이다. 만약에 몬스터가 공격 행위를 했는데 플레이어가 계속 범위안에 있을 때 다시 공격을 하지 않는 것이다..! 트리거 엔터는 트리거가 켜졌을 때만 불리기 때문이다. 이 문제는 코루틴으로 적절하게 해결하였지만 좀 찝찝하긴 하다. 아 그리고 참고로 Vector3.Dot은 단위 벡터 두 개를 넣으면 각도를 반환해 주는데 이때 몬스터 이동 방향이 필요하다. 그래서 몬스터 추적 상태일 때 Direction() 함수가 적절하게 작동하도록 수정한 것이다.
공격 범위안에 플레이어가 들어온다면 attack 변수에 의해 FixedUpdate()에서 BasicAttackMotion()이 호출된다. 당연히 여러번 호출되면 안되니까 호출되자 마자 attack bool 변수는 false가 된다. 몬스터가 공격 준비를 할 때 제자리에서 멈추어야 하므로 MonsterMove 스크립트는 false 상태로 바꾸고 코루틴으로 일정 시간 후에 공격하도록 하는 것이다.
attackReady 만큼의 시간이 지나면 Rigidbody.AddForce로 인해 앞으로 전진하면서 공격을 하게된다. 이때 플레이어가 몬스터와 충돌하면 OnCollisionEnter가 호출되고 플레이어 체력을 깎는 Attack() 함수가 호출된다. 문제는 공격이 끝나고 바로 움직이면 몬스터가 미친듯한 움직임으로 플레이어를 쫓게 되므로 일정 시간 후에 MonsterMove 스크립트를 true 상태로 바꾸는게 중요하다. 그 기능은 다시 코루틴으로 만들면 되고 위 코드에선 reMove 만큼의 시간이 지나면 몬스터가 다시 움직이도록 하였다. 그리고 ReMove 코루틴은 MonsterMove 스크립트를 켜는 것 말고도 중요한 역할을 한다. SphereCollider 범위 만큼의 OverlapSphere를 통해 근처에 플레이어가 있다면 attack 변수에 true를 대입해 다시 공격하도록 하는 것이다. 이 기능을 통해 OnTriggerEnter의 플레이어가 범위안에 계속 있다면 다시 호출되지 않는 문제점을 고쳤다. 하지만 Enter과 Exit는 가끔 호출되지 않는 문제점이 있는데 위 코드도 그렇다. 어쩔때는 몬스터가 멍청하게 플레이어한테 달려가기만 한다. 공격 기능을 켜지 않는 것이다. 이건 일단 나중에 생각하기로 하였다. |