시야 내 타겟 자동 설정 - Field of VIew

Published: Jul 30, 2021 by BeatChoi

몬스터의 시야를 설정하고 타겟을 자동 설정해보기.

시야 :: Field of View

AI 캐릭터가 필요한 콘텐츠에서는 AI 캐릭터의 시야와 해당 캐릭터가 플레이어를 선택하는 조건등을 고민하게 됩니다.
Field of View를 AI 캐릭터에 설정하여 해당 캐릭터의 시야에 플레이어가 들어오게 되면 자동으로 타겟팅 할수 있도록 해봅니다.

유니티3D 에디터에서

스크립트 생성

먼저 fieldofview.cs 스크립트를 생성하고 다음과 같이 작성합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class fieldofview : MonoBehaviour
{

    public float viewArea;
    [Range(0,360)]
    public float viewAngle;

    public LayerMask targetMask;

    [HideInInspector]
    public List<Transform> Targets = new List<Transform>();

    // Update is called once per frame
    void Update()
    {
        GetTarget();
    }

    public void GetTarget()
    {
        Targets.Clear();
        Collider[] TargetCollider = Physics.OverlapSphere(transform.position, viewArea, targetMask);

        for(int i = 0; i < TargetCollider.Length; i++)
        {
            Transform target = TargetCollider[i].transform;
            Vector3 direction = target.position - transform.position;
            if(Vector3.Dot(direction.normalized, transform.forward) > GetAngle(viewAngle / 2).z)
            {
                Targets.Add(target);
            }
        }
    }

    public Vector3 GetAngle(float AngleInDegree)
    {
        return new Vector3(Mathf.Sin(AngleInDegree * Mathf.Deg2Rad), 0, Mathf.Cos(AngleInDegree * Mathf.Deg2Rad));
    }


    private void OnDrawGizmos()
    {
        Handles.DrawWireArc(transform.position, Vector3.up, transform.forward, 360, viewArea);
        Handles.DrawLine(transform.position, transform.position + GetAngle(-viewAngle / 2) * viewArea);
        Handles.DrawLine(transform.position, transform.position + GetAngle(viewAngle / 2) * viewArea);

        foreach(Transform Target in Targets)
        {
            Handles.DrawLine(transform.position, Target.position);
        }
    }
}
  • 상단부네임스페이스란에 UnityEditor 네임스페이스를 추가합니다. 씬 창에서 가상의 범위를 나타내주는 메소드를 호출할 수 있습니다.
  • ViewArea는 캐릭터를 중심으로 반지름 거리의 값을 나타냅니다.
  • ViewAngle은 캐릭터 정면의 시야 각도입니다.
    • 캐릭터의 반지름 거리에 있는 플레이어 중 캐릭터의 시야 각 내에 있는 플레이어를 타겟팅 할수 있도록 합니다.
  • GetTarget은 타겟을 선정하는 함수입니다.
    • Collider형의 배열 변수를 하나 선언한 뒤 OverlapSphere메소드로 캐릭터를 중심으로 한 가상의 원 반경 내의 충돌체들을 추출해 냅니다.
    • 반경 내 충돌체들 중 시야 각도 내에 있는 오브젝트들의 Transform값을 Targets리스트에 추가합니다.
  • GetAngle은 설정하는 시야각을 Vector3로 반환하는 역할을 합니다.
    • 해당 함수를 호출할 때 인자들을 2로 나누는 이유는 캐릭터를 중심으로 좌측으로 x도, 우측으로 x도, 두개의 각도의 합이 ViewAngle이기 때문입니다.
  • OnDrawGizmos함수는 기능적으로는 상관이 없는 함수입니다. 다만 씬 창에서 우리의 코드가 제대로 작동하는지 표현하기 위한 함수입니다.
  • UnityEditor를 통해 호출받은 Handles 클래스를 통해 캐릭터 주변 범위 및 시야각도를 선으로 표현합니다.
  • 씬 창에서만 보입니다.

프로젝트 생성 및 세팅

간단하게 Plane으로 바닥을 깔아주고 Capsule로 캐릭터, Cube로 타게팅 될 오브젝트를 생성합니다.


<01. 씬 배치>

먼저 타게팅 될 Cube 오브젝트를 선택합니다.
타게팅이 되기 위해서는 Mask Layer를 설정해줘야합니다.
Cube를 선택하고 인스펙터창 우측 상단 Layer 드롭다운버튼을 눌러서 Add Layer 버튼을 누릅니다.


<02. Mask Layer 설정>

인스펙터 창에서 비어있는 레이어 항목에 Target 레이어를 생성합니다.


<03. Mask Layer 생성>

돌아와서 다시 Cube오브젝트를 선택한 후 레이어를 Target으로 변경합니다.


<04. Mask Layer 변경>

Capsule오브젝트에 fieldofview.cs스크립트를 인스턴스화 시킵니다.
fieldofview컴포넌트에 ViewArea값과 ViewAngle값을 조정합니다.
TargetMask 항목은 아까 생성한 Target으로 설정합니다.


<05. Capsule 오브젝트 설정>

그럼 씬창은 이렇게 변합니다.


<06. 씬 창>

테스트 :: Test

상단 플레이 버튼을 눌러 Capsule 오브젝트를 이동시켜봅니다.
Cube의 범위 안, 밖으로 이동시켜 시야 내에 있을 때 서로를 잇는 흰 선이 생성되는지 확인합니다.


<07. 테스트>

정리

이번 포스팅에서는 하나의 객체의 시야 내에 있는 오브젝트를 타겟팅 하는 방법에 대하여 진행했습니다.
이는 몬스터 AI를 설정할 때 자주 활용되는 기법이며 플레이어의 타겟팅을 예로 들었지만 시야 범위 내에 어떠한 행위를 하기위한
범위 설정을 할수있는 광범위한 기법입니다.

Latest Posts

콘텐츠 개발 기법 - URP 환경에서 Bloom 및 Volume 포함한 화면 캡처
콘텐츠 개발 기법 - URP 환경에서 Bloom 및 Volume 포함한 화면 캡처

화면 캡처 :: Screen Capture

일반적으로 URP환경에서 Bloom 등의 Volume 이펙트들이 함께 캡처되지 않는 현상이 일어납니다.
두가지 원인이 있는데 첫번째는 저장할 Texture 및 Texture2D의 크기가 작아 모든 텍스쳐를 저장할 수 없는 경우와
두번째는 Linear color space의 픽셀을 텍스쳐에 저장 할 수 없는 경우가 있습니다.
이번 포스팅에서는 URP 환경에서 해당 이펙트들을 함께 캡쳐하는 방법을 알아봅니다.

콘텐츠 개발 기법 - UI 안나오게 화면 캡처(Screen Capture without UI)
콘텐츠 개발 기법 - UI 안나오게 화면 캡처(Screen Capture without UI)

화면 캡처 :: Screen Capture

UI 없이 화면을 캡쳐하는 방법을 알아봅니다.
해당 방법을 통해 사진 앱에서 사진을 찍거나 게임 내에서 UI를 제거한 스크린샷을 구현할 수 있습니다.

유니티3D 에디터에서

스크립트 작성

LightshipAR SDK 활용하기 - LightshipAR VPS의 활용
LightshipAR SDK 활용하기 - LightshipAR VPS의 활용

LightshipAR SDK

이번 강좌에서는 Visual Positioning System (VPS) 기능을 활용하여 콘텐츠를 개발해 봅니다.
VPS는 GPS정보와 타겟 매핑 정보를 정합하여 해당 타겟을 인식하는 기능입니다.
따라서 객체나 환경의 변화 및 이동이 잦지 않은 타겟이 스캔 대상이 됩니다.
주로 동상, 건물 입구, 가로등 등 위치의 변경이 없는 타겟들이 좋은 타겟입니다.

해당 타겟들을 인식시키고 주변에 가상의 오브젝트들을 배치하고 해당 위치를 저장하는 방법을 알아봅니다.

공간 매핑

Niantic Wayfarer

공간을 인식시키기 위해서 먼저 공간을 매핑해야 합니다.
이 과정은 IOS 어플리케이션으로 진행을 할 수 있는데 아래 링크에서

  1. Testflight
  2. Wayfarer

어플리케이션을 다운로드 및 설치합니다.

링크 : https://testflight.apple.com/join/VXu1F2jf