Vector3, Quaternion Angle 안 쓰고 적 시야탐지 구현

devKyoun·2024년 10월 18일
0

Unity

목록 보기
18/27
post-thumbnail

왜 Quaternion,Vector3 Angle 구현을 안했냐면 성능비용은 그렇게 큰 문제점은 안됐는데
0~180도 사이 즉, 음수 반환을 하지 않아서 상당한 커스터마이징 해야한다는게 싫었다

또 어떤 코드가 있긴 했는데 꼭 각도를 구하려고 식 계산을 해버리는게 있어서 좀 그랬다
내 코드에선 FSM의 특정한 Update에서 계속 적 시야각을 확인해야하는데 매번 계산을 한다라..


	내가 하려는 코드 아님

    public static float GetAngle (Vector3 vStart, Vector3 vEnd)
    {
        Vector3 v = vEnd - vStart;
 
        return Mathf.Atan2(v.y, v.x) * Mathf.Rad2Deg;
    }

출처

해결안

 private bool SeeingPlayer()
 {
     Vector3 enemyForwardDir = enemyManager.transform.forward;
     enemyForwardDir.y = 0;
     enemyForwardDir.Normalize();

     Vector3 enemyPlayerDir = enemyManager.PlayerInteractHandler.transform.position - enemyManager.transform.position;
     enemyPlayerDir.y = 0;
     enemyPlayerDir.Normalize();

     if(enemyForwardDir.z * enemyPlayerDir.z > 0  && enemyForwardDir.x * enemyPlayerDir.z > 0 )
     {
         return true;
     }
     else
     {
         return false;
     }
 }

현재 코드는 디테일한 각도 설정은 안된다는 점 주의
할려면 z가 음수,양수 x가 음수,양수 모든 경우의 수 추가해줘야 함


  Vector3 enemyForwardDir = enemyManager.transform.forward;
  enemyForwardDir.y = 0;
  enemyForwardDir.Normalize();

  Vector3 enemyPlayerDir = enemyManager.PlayerInteractHandler.transform.position - enemyManager.transform.position;
  enemyPlayerDir.y = 0;
  enemyPlayerDir.Normalize();

enemyForwardDir은 현재 enemy가 바라보고있는 정면이다

enemyPlayerDir은 현재 enemy Transform에서 player Transform을 보는 벡터이다
즉 실질적으로 적이 플레이어를 보려면 enemyPlayerDir의 대략적인 방향을 바라봐야 한다는 것

이러면 못본다는 것
Enemy가 바라보는 저 벡터는 x가 음수이고 z가 -0.1~0.1 정도 될 것
Player을 감지하려면 Player를 바라보는 벡터가 x가 양수이기 때문에 애당초 보지를 못함

바로 아래 부분도 각 벡터가 z의 부호가 다르기 때문에 확인 못함

즉, Enemy의 실질적인 정면 벡터와 가상으로 Player를 똑바로 바라보는 경우의 벡터. 두 벡터가 x,z 각각 부호가 같아야한다

if(enemyForwardDir.z * enemyPlayerDir.z > 0  && enemyForwardDir.x * enemyPlayerDir.x > 0 )
    {
        return true;
    }
    else
    {
        return false;
    }
 }

결과

밑에 콘솔에 False, True는 Player를 감지 못했다, 했다를 나타낸다.
중간에는 NotMoving이라는 건데 무시해도 된다.
(전에 최적화 할때 확인용도로 Debug 해놓은 것)

EnemyRoamingState.cs ( FSM State )

 public override void StateUpdate()
 {
     // 여기서 감지되면 Trancking으로 ChangeState 해주면 됨
     Debug.Log(SeeingPlayer());

     if (setRoamPos)
     {
         path = new NavMeshPath();
         enemyManager.EnemyNavAgent.CalculatePath(roamPosition, path);
         enemyManager.EnemyNavAgent.SetPath(path);
         path = null;

         setRoamPos = false;
         enemyManager.Animator.SetBool(enemyManager.AnimIDWalk, true);

     }

     if (enemyManager.EnemyNavAgent.remainingDistance <= enemyManager.EnemyNavAgent.stoppingDistance)
     {
         enemyManager.Animator.SetBool(enemyManager.AnimIDWalk, false);
         // 도착 했을때, Timer 시작
         waitCounter += Time.deltaTime;

         if (waitCounter >= enemyManager.WaitTime)
         {
             setRoamPos = true;
             roamPosition = GetRoamingPosition();
             waitCounter = 0;
         }
     }
 }
profile
Game Developer

0개의 댓글