본문 바로가기

Project/도둑과 경호원

[도둑과 경호원] Unity: Guard 플레이어 검거하기

728x90

Guard에게 플레이어가 일정 범위 안에 들어갔을 때 플레이어를 검거할 수 있는 로직을 구현해보겠습니다.

 

1
2
3
4
5
6
7
8
9
10
    public Light spotLight;
    public float viewDistance = 5;
    public LayerMask viewMask;
    public float timeToSpotPlayer = 0.5f;
 
    float playerVisibleTimer;
    float viewAngle;
    
    Transform player;
    Color originalSpotlightColor;

 

 

  • spotLight - Guard가 가지고 있는 spotLight를 저장할 변수이다.
  • viewDistance - Guard가 플레이어를 검거할 수 있는 직선거리이다.
  • viewMask - LayerMask를 담아줄 변수이다.
  • timeToSpotPlayer - 플레이어가 검거되기까지의 시간을 저장할 변수이다.
  • playerVisibleTimer - 플레이어가 검거되고 있는 시간을 저장할 변수이다.
  • viewAngle - Guard가 플레이어를 볼 수 있는 각도를 저장할 변수이다.
  • player - 플레이어의 Transform을 저장할 변수이다.
  • originalSpotlightColor - spotLight의 처음 색깔을 저장할 변수이다.

 

1
2
3
4
5
6
void Start()
    {
        viewAngle = spotLight.spotAngle;
        player = FindObjectOfType<Player>().transform;
        originalSpotlightColor = spotLight.color;
    }

 

초기화가 필요한 변수들을 초기화해준다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
bool CanSeePlayer()
    {
        if(Vector3.Distance(transform.position, player.position) < viewDistance)
        {
            Vector3 dirToPlayer = (player.position - transform.position).normalized;
            float angleBetweenGuardAndPlayer = Vector3.Angle(transform.forward, dirToPlayer);
            if(angleBetweenGuardAndPlayer < viewAngle / 2)
            {
                if(!Physics.Linecast(transform.position, player.position, viewMask))
                {
                    return true;
                }
            }
        }
        return false;
    }

 

일단 Guard와 플레이어의 거리가 viewDistance보다 작은지 확인한다. 그리고 Guard에서 플레이어쪽 방향의 벡터3를 구하고 정규화 해준다. Vector3.Angle값을 이용하여 Guard와 플레이어의 각도를 구한다. 그리고 구한 각도가 Guard가 볼 수 있는 각도보다 작은지 확인해준다. 만약 그 값이 참이고 Physics.Linecast값 Guard와 플레이어 사이에 장애물이 없다면 true를 반환하고 아니라면 false를 반환해준다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void Update()
    {
        if (CanSeePlayer())
        {
            playerVisibleTimer += Time.deltaTime;
        }
        else
        {
            playerVisibleTimer -= Time.deltaTime;
        }
        playerVisibleTimer = Mathf.Clamp(playerVisibleTimer, 0, timeToSpotPlayer);
        spotLight.color = Color.Lerp(originalSpotlightColor, Color.red, playerVisibleTimer / timeToSpotPlayer);
 
        if(playerVisibleTimer >= timeToSpotPlayer)
        {
            if(OnGuardSpottedPlayer != null)
            {
                OnGuardSpottedPlayer();
            }
        }
    }

 

CanSeePlayer가 true라면 playerVisibleTimer를 올려주고 아니라면 playerVisibleTimer를 내려준다. Mathf.Clamp를 사용하여 0, tiemToSpotPlayer값을 벗어나지 않는 playerVisibleTimer를 만들어준다. 그리고 Color.Lerp를 사용하여playerVisibleTimer가 늘어남에 따라 spotLight의 색깔을 originalSpotlightColor에서Color.red로 바꿔준다. 그리고 만약에 playerVisibleTimer가 TimeToSpotPlayer보다 값이 커지게 되면 OnGuardSpottedPlayer를 실행시켜준다.

 

728x90