블로그 이미지
한국IT전문학교 게임프로그래밍 2018년 졸업생 / 배우고 익히고 정리하는 곳 무명의 공룡

카테고리

분류 전체보기 (133)
Unity (5)
AR / VR (8)
홀로렌즈2 (2)
Unity 3D 액션 게임 제작 (2)
정리 (9)
소소한 배움 (6)
그외 (7)
비공개 (56)
--이전 프로젝트들-- (0)
Tree-sha (팀 3D) (9)
Icicle Game (2D) (19)
MMD RPG (3D) (9)
Total
Today
Yesterday

달력

« » 2024.5
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

공지사항

Unity 2D FOV 연출

Unity/2020 / 2020. 6. 24. 15:58

본 글은 Code Monkey의 영상을 참고하였습니다. 

https://unitycodemonkey.com/video.php?v=CSeUMTaNFYk

 

Code Monkey - Field of View Effect in Unity (Line of Sight, View Cone)

Field of View Effect in Unity (Line of Sight, View Cone) 13/10/2019 Let's make an awesome Line of Sight effect that interacts with walls, enemies outside the Field of View are not visible. Excellent effect for any sort of Stealth or Horror game.

unitycodemonkey.com

 

 

2D FOV 연출.. 뭐 이런거

2D 게임에서 종종 보이는 방법입니다.

잘만 활용하면 단조로운 맵도 입체감 있게 만들 수 있고 공포 분위기 연출에 훌륭한 방법 중 하나입니다.

 

여러가지 방법이 있겠지만 여기선 매프레임 수십번의 레이를 쏘아 레이 도착점을 이어 메쉬를 그리는 방법입니다.

코드가 쉬운 편이고 퀄리티와 퍼포먼스에 주는 영향도 직관적입니다.

 

위 코드몽키 영상에서 나온 코드에서 살짝 손을 보아 시야각을 그리는 방식은 동일하지만 다루기 더 편하게 만들어본 코드입니다.

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
using UnityEngine;
 
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
 
public class FieldOfView : MonoBehaviour
{
    [Range(0360)] public float fov = 90f;     //시야각
    public int rayCount = 90;                   //레이의 수 (높을수록 퀄리티↑퍼포먼스↑)
    public float viewDistance = 10f;            //거리
    public LayerMask layerMask;                 //벽으로 인식할 레이어
 
    private Camera mainCamera;                  //카메라
    private Mesh mesh;                          //시야각을 그려줄 메쉬
 
    private void Start()
    {
        mainCamera = Camera.main;
        mesh = new Mesh();
        mesh.name = "FOV_Effect";
        GetComponent<MeshFilter>().mesh = mesh;
    }
 
    private void LateUpdate()
    {
        Vector3 mousePosition = mainCamera.ScreenToWorldPoint(Input.mousePosition);
        transform.eulerAngles = new Vector3(00, GetAngleFromVector(new Vector3(mousePosition.x - transform.position.x, mousePosition.y - transform.position.y, 0)));
        DrawFOV();
    }
 
    private void DrawFOV()
    {
        float angle = fov * 0.5f;
        float angleIncrease = fov / rayCount;
 
        Vector3[] vertices = new Vector3[rayCount + 1 + 1];
        Vector2[] uv = new Vector2[vertices.Length];
        int[] triangles = new int[rayCount * 3];
 
        vertices[0= Vector3.zero;
 
        int vertexIndex = 1;
        int triangleIndex = 0;
        for (int i = 0; i <= rayCount; i++)
        {
            Vector3 vertex;
            RaycastHit2D raycastHit2D = Physics2D.Raycast(transform.position, GetVectorFromAngle(transform.eulerAngles.z + angle), viewDistance, layerMask);
            if (raycastHit2D.collider == null)
            {
                vertex = GetVectorFromAngle(angle) * viewDistance;
            }
            else
            {
                vertex = GetVectorFromAngle(angle) * (raycastHit2D.distance / viewDistance) * viewDistance;
            }
            vertices[vertexIndex] = vertex;
 
            if (0 < i)
            {
                triangles[triangleIndex + 0= 0;
                triangles[triangleIndex + 1= vertexIndex - 1;
                triangles[triangleIndex + 2= vertexIndex;
 
                triangleIndex += 3;
            }
 
            ++vertexIndex;
            angle -= angleIncrease;
        }
 
        mesh.vertices = vertices;
        mesh.uv = uv;
        mesh.triangles = triangles;
    }
    private Vector3 GetVectorFromAngle(float angle)
    {
        float angleRad = angle * (Mathf.PI / 180f);
        return new Vector3(Mathf.Cos(angleRad), Mathf.Sin(angleRad));
    }
    private int GetAngleFromVector(Vector3 dir)
    {
        dir = dir.normalized;
        float n = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
        if (n < 0) n += 360;
        int angle = Mathf.RoundToInt(n);
 
        return angle;
    }
}
cs

 

아래 GetVectorFromAngle, GetAngleFromVector 함수는 원래 코드몽키 유틸리티용 코드에 포함된 함수입니다만 한 눈에 보기 쉬우라고 옮겨놨습니다.

 

rayCount값의 경우 fov와 동일해야 제일 깔끔하게 나오는 것 같습니다.

rayCount가 더 높아도 좋겠지만 그만큼 퍼포먼스가 상승합니다.

 

 

참고로 GIF에서 벽 테두리가 보이는 것은 쉐이더 효과라 위 코드만으론 불가능합니다.

'Unity > 2020' 카테고리의 다른 글

오큘러스 퀘스트 2  (0) 2020.11.17
뒤끝 서버  (0) 2020.11.16
Addressable Asset system 간단하게 서버 다운로드로 실사용까지  (6) 2020.06.23
Posted by 무명의 공룡
, |