본문 바로가기
게임 개발/유니티 게임 개발 일지

#6 캐릭터 구현하기 - Field Of View 캐릭터 시야 구현하기

by FlowTree 2020. 2. 19.
반응형

Field Of View 구현 목적

캐릭터의 시야 안에 있는 적을 식별하고, 타겟팅하여 공격하기 위함이다.

 

Field Of View 구현할 기능

1.캐릭터 전방으로 부채꼴 형태의 시야 범위 구현

2.시야 범위 안에 오브젝트가 존재하는지 판단

3.시야 범위 안에 존재할 경우 어떤 오브젝트인지 식별(Target, Obstacle)

4.Target의 경우 타겟팅

5.재식별 기능(코루틴)

6.타겟팅 우선 순위 기능(캐릭터와 가장 가까운 적을 우선적으로 Target) - 미구현

7.기타 타겟팅 기능(타겟팅 시 몇 초간 유지? - 몬스터와 전투 테스트를 진행 후 구현할 예정) - 미구현

 

Field Of View 참고 자료

Sebastian Lague님의 Field Of View 영상을 발견했지만 자막이 없어서 이해를 못했다.

해당 링크에 관련 자료를 얻을 수 있어서 스크립트파일을 볼 수 있었다.

https://www.youtube.com/watch?v=rQG9aUWarwE

 

유니티 공식 유튜브에서 (Stealth game tutorial - 403 - Enemy Sight and Hearing - Unity Official Tutorials)

위의 내용과 같은 영상을 찾았다. 특히 한글 자막이 있어서 쉽게 이해할 수 있었다. 해당 영상에서는 소리듣기 기능도 있지만 앞부분의 Sight 기능만 필요하여 참고했다.

https://www.youtube.com/watch?v=mBGUY7EUxXQ

Field Of View 스크립트

 

using System.Collections; 
using System.Collections.Generic; 
using UnityEngine; 

public class FieldOfView : MonoBehaviour 
{ 
    public float viewRadius; 
    [Range(0, 360)] 
    public float viewAngle; 

    public LayerMask targetMask; 
    public LayerMask obstacleMask; 
    //있어야함, 왜냐면 타겟 사이에 다른 오브젝트가 있는데 그 오브젝트를 투과해서 뒤의 타겟오브젝트를 볼 수 있음 

    public List visibleTargets = new List(); 

    void Start() 
    { //플레이 시 FindTargetsDelay 코루틴을 실행한다. 0.5초 간격으로 
        StartCoroutine("FindTargetsDelay", .5f); 
    } 

    IEnumerator FindTargetsDelay(float delay) 
    { 
        while (true) 
        { 
            yield return new WaitForSeconds(delay); 
            FindTargets(); 
        } 
    } 

    void FindTargets() 
    { 
        Collider[] targetInViewRadius = Physics.OverlapSphere(transform.position, viewRadius, targetMask); 

        for (int i = 0; i < targetInViewRadius.Length; i++ ) 
        //ViewRadius 안에 있는 타겟의 개수 = 배열의 개수보다 i가 작을 때 for 실행 

        { 
            Transform target = targetInViewRadius[i].transform; //타겟[i]의 위치 
            Vector3 dirToTarget = (target.position - transform.position).normalized; 
             //vector3타입의 타겟의 방향 변수 선언 = 타겟의 방향벡터, 타겟의 position - 이 게임오브젝트의 position) normalized 
                  = 벡터 크기 정규화 = 단위벡터화 

            if (Vector3.Angle(transform.forward, dirToTarget) < viewAngle / 2) 
             // 전방 벡터와 타겟방향벡터의 크기가 시야각의 1/2이면 = 시야각 안에 타겟 존재 

            { 
                float dstToTarget = Vector3.Distance(transform.position, target.position); //타겟과의 거리를 계산 
                if (!Physics.Raycast(transform.position, dirToTarget, dstToTarget, obstacleMask)) 
                  //레이캐스트를 쐈는데 obstacleMask가 아닐 때 참이고 아래를 실행함 

                { 
                    visibleTargets.Add(target); 
                    print("raycast hit!"); 
                    Debug.DrawRay(transform.position, dirToTarget * 10f, Color.red, 5f); 
                } 
            } 
        } 
    } 
     
}

 

https://www.youtube.com/watch?v=DSmPGCw-iAc

 

반응형

댓글