private INode.E_NodeState CheckDetectPlayer()
{
var overlapColliders =
Physics.OverlapSphere(transform.position, _detectDistance, LayerMask.GetMask("Player"));
// 추후 범위 안에 있으면 한번만 할당하게 변경
if (overlapColliders != null & overlapColliders.Length> 0)
{
_detectedPlayer = overlapColliders[0].transform;
// 순찰 노드 최초확인 bool값 초기화.
_patrolRandomPosCheck = true;
_idleWaitCheck = true;
return INode.E_NodeState.ENS_Success;
}
_detectedPlayer = null;
return INode.E_NodeState.ENS_Failure;
}
private INode.E_NodeState CheckPlayerWithineAttackDistance()
{
if (_detectedPlayer != null)
{
if (Vector3.SqrMagnitude(_detectedPlayer.position - transform.position) <
(_attackDistance * _attackDistance))
{
NavMeshAgentAttackSetting();
return INode.E_NodeState.ENS_Success;
}
}
return INode.E_NodeState.ENS_Failure;
}
private bool IsAnimationRunning(string animationName)
{
if (_animator != null)
{
if (_animator.GetCurrentAnimatorStateInfo(0).IsName((animationName)))
{
var normalizedTime = _animator.GetCurrentAnimatorStateInfo(0).normalizedTime;
return normalizedTime != 0 && normalizedTime < 1f;
}
}
return false;
}
공격분기 노드에서 가장 첫번째 검사 현재 공격중인지를 체크한다.
Attack Animation을 NormalizedTime으로 변환하여 실행중인지를 bool값으로 체크한다. (공격중인지를 가장 처음 검사해야 이미 공격하는 중인데 또 공격을 실행하지 않는다.)
private INode.E_NodeState CheckPlayerWithineAttackDistance()
{
if (_detectedPlayer != null)
{
if (Vector3.SqrMagnitude(_detectedPlayer.position - transform.position) <
(_attackDistance * _attackDistance))
{
NavMeshAgentAttackSetting();
return INode.E_NodeState.ENS_Success;
}
}
return INode.E_NodeState.ENS_Failure;
}
private INode.E_NodeState DoAttack()
{
if (_detectedPlayer != null)
{
IsAnimationAttackCheck();
return INode.E_NodeState.ENS_Success;
}
return INode.E_NodeState.ENS_Failure;
}
private INode.E_NodeState DoTracking()
{
if (_detectedPlayer != null)
{
NavMeshAgentTrackingSetting();
_agent.SetDestination(_detectedPlayer.position);
}
return INode.E_NodeState.ENS_Failure;
}
범위안에 플레이어가 있어서 _dectedPlayer가 할당이 되어었는데 공격 범위안에 적이 없다면 이쪽 추적 노드로 넘어와서 Agent의 목적지를 플레이어로 설정해줘서 플레이어를 따라가도록 한다.
이 때, 애니메이션은 추적용 Run Animation이 실행된다.
공격 애니메이션 Attack 애니메이션과 트랜지션 IsAttack
추적 애니메이션 Run 애니메이션과 트랜지션 IsRun
범위 안에서 감지되면 무조건 Run Animation으로 추적을 실행하다가, 공격을 진행하기에 Attack으로 가는 트랜지션은 Run에서만 이어주는것으로 충분하다 생각했다.
좀비가 플레이어를 공격하면 가만히 있어야하는 공격 애니메이션 인데도 공격하면서 움직이거나, 속도를 올려도 바뀌지 않고, 런닝머신을 타는것 처럼 움직였다.
private void NavMeshAgentAttackSetting()
{
IsAnimationAttackCheck();
_animator.applyRootMotion = false;
_agent.isStopped = true;
_agent.updatePosition = false;
_agent.updateRotation = false;
_agent.velocity = Vector3.zero;
}
private void NavMeshAgentTrackingSetting()
{
IsAnimationRunCheck();
_animator.applyRootMotion = false;
_agent.speed = _agentTrkingSpeed;
_agent.isStopped = false;
_agent.updatePosition = true;
_agent.updateRotation = true;
}
private void NavMeshAgentPatrolSetting()
{
IsAnimationWalkCheck();
_animator.applyRootMotion = true;
_agent.speed = _agentSpeed;
_agent.SetDestination(_correctPos);
_patrolRandomPosCheck = false;
}
그래서 코드적으로 필요한 부분에서는 켰다가, 그 부분이 지나면 꺼주는 방식으로 보완하였다.
세팅해줘야하는 값들을 메서드로 묶어 관리가 편하고 가독성이 좋게 하였다.
애니메이터 수정 필요
(너무 꼬이고 불필요하게 겹치는 부분이 있음)
플레이어 감지를 할 때, 물체에 가려지면 감지 불가능하게 하도록 조정.
소리로 감지하는 범위, 시야로 감지하는 범위로 분할.
플레이어가 시야에서 사라지면 두리번거리는 애니메이션 한번 하고 순찰하면 좋을것같다.