Unity 최종 프로젝트 - 10

이준호·2024년 1월 25일
0

📌 Unity 최종 프로젝트



📌 추가사항

➔ Zombie Attack

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


  • 가장 첫번째 노드인 "범위 안에 적이 있는가?"에서 적이 있다면 _dectedPlayer에 플레이어의 Transform정보가 할당되고 공격분기의 노드로 들어온다.
    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;
    }
  • 공격중이 아니라고 판단이 되면 이제 공격범위 _attackDistance안에 플레이어가 있는가를 판단한다.


    private INode.E_NodeState DoAttack()
    {
        if (_detectedPlayer != null)
        {
            IsAnimationAttackCheck();
            return INode.E_NodeState.ENS_Success;
        }

        return INode.E_NodeState.ENS_Failure;
    }
    1. 플레이어가 공격 범위안에 있는것이 확인되면 그 때서야 공격을 실행한다.



➔ Zombie Tracking

    private INode.E_NodeState DoTracking()
    {
        if (_detectedPlayer != null)
        {
            NavMeshAgentTrackingSetting();
            _agent.SetDestination(_detectedPlayer.position);
        }

        return INode.E_NodeState.ENS_Failure;
    }
  • 범위안에 플레이어가 있어서 _dectedPlayer가 할당이 되어었는데 공격 범위안에 적이 없다면 이쪽 추적 노드로 넘어와서 Agent의 목적지를 플레이어로 설정해줘서 플레이어를 따라가도록 한다.

  • 이 때, 애니메이션은 추적용 Run Animation이 실행된다.




➔ Zombie Animation

  • 공격 애니메이션 Attack 애니메이션과 트랜지션 IsAttack

  • 추적 애니메이션 Run 애니메이션과 트랜지션 IsRun

  • 범위 안에서 감지되면 무조건 Run Animation으로 추적을 실행하다가, 공격을 진행하기에 Attack으로 가는 트랜지션은 Run에서만 이어주는것으로 충분하다 생각했다.












📌 트러블 슈팅

➔ Apply Root Motion

좀비가 플레이어를 공격하면 가만히 있어야하는 공격 애니메이션 인데도 공격하면서 움직이거나, 속도를 올려도 바뀌지 않고, 런닝머신을 타는것 처럼 움직였다.

이유

  • 저번에 했던 자연스러운 애니메이션의 움직임을 위해 켜두었던 "Apply Root Motion" 때문에 속도를 지정해줘도 애니메이션의 움직임에 맞춰서만 움직여 이상한 움직임을 보이게 된 것이었다.

해결 방법

    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;
    }
  • 그래서 코드적으로 필요한 부분에서는 켰다가, 그 부분이 지나면 꺼주는 방식으로 보완하였다.

  • 세팅해줘야하는 값들을 메서드로 묶어 관리가 편하고 가독성이 좋게 하였다.












📌 추가&보완 해야할 사항

  • 애니메이터 수정 필요
    (너무 꼬이고 불필요하게 겹치는 부분이 있음)

  • 플레이어 감지를 할 때, 물체에 가려지면 감지 불가능하게 하도록 조정.

  • 소리로 감지하는 범위, 시야로 감지하는 범위로 분할.

  • 플레이어가 시야에서 사라지면 두리번거리는 애니메이션 한번 하고 순찰하면 좋을것같다.

profile
No Easy Day

0개의 댓글