반응형

안녕하세요! 여러분들과 함께 게임 개발을 공부하는 베르입니다!

이번에는 함께 일하는 다른 팀원들에게 에셋을 전달하기 위해서 사용되는 유니티 패키지에 대해서 알아봅시다.

 

사용 엔진 버전 : 2020.3

 

타임라인

0:00 인트로

0:11 압축파일 전달

1:15 유니티 패키지

2:45 버전 관리 도구로써는? 글쎄...

3:41 유니티 패키지 사용법

4:59 아웃트로

 

스크립트

인트로

안녕하세요. 여러분들과 함께 게임 개발을 공부하는 베르입니다.

이번 영상에서는 유니티에서 에셋을 전달하기 위해서 사용되는 유니티 패키지에 대해서 알아보도록 하겠습니다.

압축파일 전달

유니티에 익숙하지 못한 입문자일 때는 프로젝트나 프로젝트 안에 있는 텍스처, 머티리얼, 프리팹, 스크립트 같은 에셋을 공유하거나 전달하려고 프로젝트 전체를 압축해서 보내거나 전달할 에셋을 선택하여 압축해서 보내는 방법을 주로 사용했었습니다.

저도 유니티를 처음 배웠을 때는 그렇게 많이 했었죠.

하지만 이 방법을 사용하면 굉장히 많은 문제가 발생합니다.

전체 프로젝트를 압축해서 옮기면 프로젝트의 크기에 따라서 압축 파일의 용량이 너무 커져서 옮기기가 어려워 집니다.

물론 프로젝트에 필요한 폴더만 묶어서 압축하면 훨씬 압축파일의 용량이 줄어들지만, 이렇게 옮기면 프로젝트를 받은 사람이 처음 열 때 시간이 많이 걸린다는 단점도 있습니다.

그리고 압축 파일 이름에 버전을 적어둬도 어떤 게 어떤 버전인지 헷갈리는 문제도 발생합니다.

거기에 가장 치명적인 단점으로는 수동으로 파일을 선택할 때는 프리팹이나 씬에 포함된 오브젝트의 참조 관계, 즉 어떤 프로퍼티에 어떤 프리팹이나 텍스처 등의 에셋들이 꽂혀있는지 전부 알 수 없기 때문에 빠지는 파일이 생길 수 있습니다.

그렇게 되면 전달된 에셋들이 제대로 동작하지 않는 문제가 발생하게 됩니다.

유니티 패키지

앞에서 말한 압축 파일로 에셋을 전달하는 방법에서 발생하는 문제를 해결할 수 있는게 바로 유니티 패키지입니다.

먼저 유니티 패키지를 만드는 방법부터 보여드리겠습니다.

유니티 에디터의 프로젝트 뷰에서 유니티 패키지로 익스포트할 에셋을 선택합니다.

그 에셋에 우클릭하고 [Export Package]를 선택합니다.

그러면 Exporting Package 창이 뜨면서 선택한 에셋과 연관된 에셋, 즉 종속성을 가진 에셋들이 함께 자동으로 선택됩니다.

물론 프로젝트 크기가 커지면 이 종속성이 상당히 복잡해서 정말 필요한 에셋 뿐만 아니라 곁다리 수준으로만 엮인 에셋들도 선택되서 쓸데없는 에셋들이 함께 익스포트되는 경우도 있기 때문에 잘 확인하고 꼭 익스포트할 에셋들만 선택해야 합니다.

그리고 창에서 Include dependency 체크를 해제하면 정말 선택한 에셋만 잡히는데 지금 선택한 프리팹의 경우에는 필요한 3D 모델, 애니메이터 컨트롤러 등이 모두 빠지기 때문에 빈 오브젝트만 익스포트됩니다.

그래서 이 Include dependency 옵션은 보통은 정말 필요한 리소스 에셋이나 스크립트 에셋만 빼내야 할 때 체크를 해제해주면 됩니다.

이렇게 익스포트할 에셋을 모두 선택한 다음에는 Export 버튼을 누르고 저장하고자 하는 위치에 이 패키지가 무엇을 담고 있는지 확실하게 알 수 있는 이름으로 저장해주면 됩니다.

그리고나서 이 유니티 패키지를 임포트할 프로젝트를 실행하고 패키지 파일을 더블클릭해주면 패키지 안에 담긴 에셋들을 그 프로젝트에 넣을 수 있게 됩니다.

버전 관리 도구로써는? 글쎄...

이렇게 유니티 패키지를 사용하면 자신이 개발한 내용이나 기능, 에셋 등을 다른 사람에게 공유할 수 있게 됩니다.

하지만 유니티 패키지를 프로젝트의 버전 관리 도구처럼 사용하려고 해서는 안됩니다.

프로젝트의 버전 관리는 개발 내용의 최신화가 아주 중요한데, 패키지를 전달 받은 다른 개발자가 자신의 프로젝트에 적용하는 작업을 까먹고 안할 수도 있고, 전달 과정에서 몇몇 사람들을 빼먹고 전달하는 경우도 있을 수 있어서 프로젝트의 최신화를 공통적으로 유지하기 어렵습니다.

그리고 이 패키지를 임포트하는 작업은 같은 에셋이 존재하는 경우에 수정 사항을 완전히 덮어씌워버리기 때문에 작업 내용이 겹치거나 잘못된 작업이 임포트되었을 때, 되돌릴 방법이 없다는 것도 문제입니다.

그렇기 때문에 유니티 패키지는 프로젝트의 버전 관리를 위한 방법으로는 적절하지 못하며, 프로젝트 버전 관리는 SVN이나 깃을 사용하는 것이 좋습니다.

깃허브를 이용해서 유니티 프로젝트를 관리하는 방법을 소개하는 영상은 영상 링크를 통해서 확인하실 수 있습니다.

유니티 패키지 사용법

그러면 유니티 패키지는 어디에 사용하면 좋은지 궁금하신 분들이 계실 겁니다.

물론 저는 거기에 답변을 드려야겠죠.

유니티 패키지는 필요한 에셋들을 선택해서 각 에셋 사이의 참조나 종속성 연결을 끊기지 않게 가져올 수 있다는 점에 초점을 맞춰야 합니다.

그래서 필요한 에셋들을 다른 프로젝트에서 가져올 수 있는 것입니다.

예를 들어 예전에 만들었던 게임이 있다고 해봅시다.

그리고 그 다음 게임을 만들려고 하는데 예전에 만들었던 게임과 유사한 형태의 인벤토리 시스템을 넣으려고 한다고 가정해봅시다.

이러면 새 프로젝트에서 완전히 새롭게 인벤토리 시스템을 짜는 것보다 이전 프로젝트에 들어있는 인벤토리 에셋들을 유니티 패키지로 익스포트해서 가져오는 편이 훨씬 나을 겁니다.

또 다른 예시로는 새 프로젝트를 만들어두고 여기에는 인벤토리 시스템만을 구현하는 방식으로 아예 특수한 기능만 구현하는 유니티 프로젝트를 만드는 것입니다.

그리고 이 프로젝트에는 이 시스템을 어떻게 사용해야 하는지 알려주는 샘플 씬과 각종 에셋, 그리고 설명서까지 넣어둡니다.

그 다음에 이 인벤토리 시스템이 필요한 프로젝트가 생기면 이 인벤토리만 구현된 프로젝트에서 관련 에셋들을 유니티 패키지로 익스포트해서 인벤토리 시스템이 필요한 프로젝트에 임포트 시키는 거죠.

사실 대부분의 유니티 에셋 스토어에 올라온 에셋들이 이렇게 필요한 기능만 구현된 프로젝트에서 패키지만 익스포트하는 방식과 유사하게 동작합니다.

아웃트로

이번 영상에서는 유니티에서 에셋을 묶어서 전달하는 기능인 유니티 패키지에 대해서 알아보았습니다.

이상 베르의 게임 개발 유튜브였습니다. 감사합니다.

반응형
반응형

 

Debug 클래스를 사용하려고 할때 System.Diagnostics 네임스페이스가 계속해서 자동으로 using 선언되는 문제와 Visual Studio에서 유니티 관련 코드가 자동완성이 되지 않는 문제에 대한 해결법을 알아봅시다!

 

타임라인

0:00 개요

0:16 using System.Diagnostics;가 계속 생겨나는 문제

3:11 Visual Studio에서 유니티 관련 자동완성이 되지 않는 문제

반응형
반응형

 

안녕하세요! 여러분들과 함께 게임 개발을 공부하는 베르입니다!

 

게임 중간에 컷씬이나 시네마틱과 같은 연출을 만드는데 좋은 유니티의 타임라인 기능에 대해서 알아봅시다!

 

사용 엔진 버전 : 2019.4

 

사운드 리소스 : https://github.com/wwer20001/wer-prog...

이펙트 리소스 : https://github.com/wwer20001/wer-prog...

 

타임라인

0:03 타임라인 개요

0:50 타임라인 에디터 열기

1:52 트랙의 종류

2:49 Activation Track

3:40 Animation Track과 무한 클립 애니메이션

4:54 Audio Track

5:37 Control Track

6:04 Signal Track

7:34 타임라인을 원하는 시점에 동작시키기

 

참고

NDC19 넥슨 코리아 마블 배틀라인 연출팀의 타임라인 사용 - http://www.gamevu.co.kr/news/articleV...

 

반응형
반응형

 

모션 캡쳐 장비인 퍼셉션 뉴런을 이용해서 모션 캡쳐하는 방법과 캡쳐한 애니메이션을 유니티로 임포트해서 사용하는 방법을 알아봅시다.

 

3D 휴머노이드 캐릭터 모델링 : https://github.com/wwer20001/wer-prog...

 

타임라인

0:08 모션 캡쳐 개요

2:29 퍼셉션 뉴런

3:16 모션 캡쳐 프로그램 액시스 뉴런 다운로드

3:48 센서 구성품

4:06 허브 USB 연결

4:15 센서 장착

4:35 센서와 프로그램 연결

4:40 센서 캘리브레이션

5:03 애니메이션 녹화

5:33 녹화된 애니메이션 익스포트

6:01 녹화된 애니메이션을 유니티에 임포트하기

7:04 액시스 뉴런 프로그램에서 유니티로 모션 캡쳐 데이터를 받아오기

8:52 모션 캡쳐로 애니메이션을 만들 때 주의점

 

참고

나무위키 모션 캡처 문서 - https://namu.wiki/w/%EB%AA%A8%EC%85%9...

퍼셉션 뉴런 - https://neuronmocap.com/

반응형
반응형

혼자 개발을 공부하다가 여러 명의 팀원들과 함께 게임을 개발을 시작했을 때, 개발한 내용을 어떻게 다른 작업자와 공유하고 프로젝트의 최신 상태를 유지할 지 궁금하신 분들이라면 필수 시청!

깃허브를 이용해서 유니티 프로젝트를 관리하고 공유하는 방법을 알아봅시다!

 

타임라인

0:06 프로젝트 관리가 필요한 이유

2:46 프로젝트를 관리하기 위한 프로그램과 서비스

3:28 깃허브 가입 방법

3:55 깃허브 웹사이트의 기본

4:47 새 리포지토리 만들기

5:08 리포지토리 공개 수준 설정

5:33 .gitinore 파일 설정

6:24 깃허브 데스크탑 설치하기

6:45 웹사이트에서 만든 리포지토리를 로컬에 복제하기

7:08 유니티 프로젝트를 깃허브 저장소에 업로드하기

7:45 깃허브의 기본 동작

7:59 커밋(Commit)

8:50 버리기, 디스카드(Discard)

9:10 푸시(Push)

9:27 풀(Pull)

9:58 머지(Merge)

11:36 다른 개발자를 내 리포지토리에 초대하기

12:22 유니티 프로젝트를 깃허브로 관리할 때 주의점 1 : 유니티 버전

13:32 유니티 프로젝트를 깃허브로 관리할 때 주의점 2 : 애셋 직렬화 방식

14:56 유니티 프로젝트를 깃허브로 관리할 때 주의점 3 : .meta 파일

16:26 .meta 파일의 생성/파괴 패턴

17:39 깃허브를 사용하지 않고 다른 개발자에게 파일을 보낼 때

18:13 .meta 파일이 갱신되는 경우

19:21 깃 서버에서 다른 사람의 커밋을 받을 때마다 메타파일이 바뀌는 문제가 발생할 때와 해결책

반응형
  1. 2021.06.24 09:52

    비밀댓글입니다

  2. 2021.06.24 09:52

    비밀댓글입니다

    • 2021.06.24 11:09

      비밀댓글입니다

반응형

내비게이션 시스템 (2) 

NavMeshAgent와 NavMeshObstacle

 

작성 기준 버전 :: 2019.2

 

[이 포스트는 유튜브 영상으로도 시청하실 수 있습니다]

 

이전 포스트에서는 유니티의 내비게이션 시스템 중에서 길찾기 영역을 설정하는 NavMesh에 대해서 알아보았다.

 

이번 포스트에서는 이 NavMesh 위에서 길을 찾아서 움직일 NavMeshAgent와 NavMeshAgent의 길을 방해하는 NavMeshObstacle에 대해서 알아보도록 하자.

 

NavMeshAgent

 

Agent는 내비게이션 메시 위에서 길을 찾아서 움직일 오브젝트를 의미한다.

 

 

우선 캡슐 게임 오브젝트를 하나 만들어서 내비게이션 메시 위에 배치해보자. 그리고 캡슐의 자식 게임 오브젝트로 큐브 하나를 배치하고 캡슐의 정면이 어디를 가리키고 있는지 알기 쉽게 만든다. 거기에 더해 Rigidbody 컴포넌트를 붙이고 Constraints를 전부 체크해준다.

 

그 다음에는 NavMeshAgent 컴포넌트를 부착한다.

 

게임 오브젝트 준비가 끝나면 이 NavMeshAgent를 움직이기 위해서 Moveable라는 이름으로 C# 스크립트를 생성한다.

 

using UnityEngine;
using UnityEngine.AI;   // 스크립트에서 내비게이션 시스템 기능을 사용하려면 AI 네임스페이스를 using 선언해야함

public class Moveable : MonoBehaviour
{
    // 길을 찾아서 이동할 에이전트
    NavMeshAgent agent;

    // 에이전트의 목적지
    [SerializeField]
    Transform target;

    private void Awake()
    {
        // 게임이 시작되면 게임 오브젝트에 부착된 NavMeshAgent 컴포넌트를 가져와서 저장
        agent = GetComponent<NavMeshAgent>();
    }

    void Update()
    {
        // 스페이스 키를 누르면 Target의 위치까지 이동하는 경로를 계산해서 이동
        if(Input.GetKeyDown(KeyCode.Space))
        {
            // 에이전트에게 목적지를 알려주는 함수
            agent.SetDestination(target.position);
        }
    }
}

 

유니티의 내비게이션 메시와 관련된 기능을 사용하기 위해서는 우선 AI 네임스페이스를 using 선언해줘야 한다.

 

먼저 NavMeshAgent 변수를 선언하고 Awake 함수에서 게임 오브젝트에 부착되어 있는 NavMeshAgent 컴포넌트를 가져와서 저장해준다. 그리고 agent가 목표로 잡고 찾아갈 target 변수를 Transform 타입으로 만든다.

 

그 다음에는 Update 함수에서 스페이스 키 입력을 감지하는 코드를 작성한다. 그 안에서 agent에게 목적지를 설정해주는 코드를 작성해야 한다. agent에게 가야할 목적지를 알려주는 함수는 agent.SetDestination이다.

 

매개변수로 target.position을 넣어주면 스페이스를 누를 때마다 agent가 타깃의 위치를 찾아서 경로를 계산하고 이동할 것이다.

 

 

그리고 하이어라키 뷰에서 빈 게임 오브젝트를 하나 생성하고 Target으로 이름 지은 뒤 좀 더 보기 쉽게 아이콘을 설정해준다. 다음에는 캡슐 게임 오브젝트에 Moveable 컴포넌트를 부착하고 Target 게임 오브젝트를 Target 프로퍼티에 할당해준다.

 

 

  

게임을 플레이 시켜보자. 게임 플레이가 시작되고 Target 게임 오브젝트를 적당한 위치로 가져다 놓은 다음 스페이스 키를 누르면 캡슐이 Target을 향해서 장애물과 부딪히지 않고 이동하는 것을 볼 수 있다.

 

NavMeshAgent의 프로퍼티

 

Base Offset

 

 

우선 첫 번째 프로퍼티인 Base Offset은 길을 찾을 때 사용되는 충돌 실린더의 위치이다. 이 값을 조절해보면 캡슐 게임 오브젝트가 바닥에 파묻히거나 공중에 뜨는 것을 볼 수 있다.

 

캐릭터와 에이전트의 위치를 맞추기 위해서 사용되는 프로퍼티이다.

 

Steering

 

Speed

 

Speed는 단어 그대로 에이전트가 움직이는 속도이다. 

 

Angular Speed

 

Angular Speed는 에이전트가 회전하는 속도이다.

 

Angular Speed 프로퍼티의 값은 degree/sec로 회전 속도를 결정한다.

 

Acceleration

 

Acceleration은 가속도이다. 

 

기본 값이 8에서는 에이전트가 최대 속도까지 도달하는데 어느 정도 시간이 걸리지만 20 정도로 수정해주면 빠르게 최대 속도에 도달하는 것을 볼 수 있다.

 

Stopping Distance

 

Stopping Distance는 목표와 얼마만큼의 거리를 두고 멈출 지를 결정한다.

 

이 기능은 원거리 유닛이 공격할 대상을 향해서 이동하다가 공격 가능한 사정거리에 도달하면 이동을 멈추고 공격하게 하려고 할 때 사용할 수 있다.

 

Auto Breaking

 

Auto Breaking은 에이전트가 목적지에 도착하기 직전에 감속을 시작할 것인가를 결정하는 프로퍼티이다.

 

Auto Breaking이 켜져있을 때는 도착하기 직전에 감속을 시작해서 목적지에 제대로 멈추지만 Auto Breaking을 끄고 이동을 시키면 목적지에 도착하고나서 감속을 시작하기 때문에 속도를 주체하지 못하고 목적지를 넘어간 뒤 목적지에 도착하기 위해서 계속 왔다갔다하는 모습을 볼 수 있다.

 

Obstacle Avoidance 

 

Obstacle Avoidance 파트는 다른 에이전트와 나중에 설명할 NevMeshObstacle을 어떻게 회피할 것인지를 결정하는 내용의 프로퍼티들을 가지고 있다.

 

먼저 기본 상황에서 이동하는 에이전트는 길을 막고 있는 에이전트를 향해서 이동하다가 돌아갈 길이 있으면 돌아가고 길이 없다면 살짝 밀어내고 길을 찾아간다.

 

Radius

 

Radius를 변경하면 초록색 원기둥의 두께가 두꺼워지는 것을 볼 수 있다.

 

하지만 지형인 벽과는 관계없이 다른 에이전트나 NavMeshObstacle과만 충돌하는 영역의 두께만 조절된다.

 

Height

 

Height는 에이전트끼리의 높이 충돌을 조절하는 프로퍼티이다. 

 

Quality

 

Quality는 장애물 회피 품질을 뜻한다. 

 

HighQuality로 설정하면 다른 에이전트를 회피하기 위해서 최대한 정밀한 움직임을 보이게 되고 Low Quality로 설정하면 피하는 움직임이 간소화된다. 그리고 양 쪽 다 None으로 설정하면 서로 완전히 무시하고 지나간다.

 

Priority

 

Priority는 에이전트 간의 우선 순위이다. 우선 순위는 0부터 99까지 있는데 0이 가장 높고 99가 가장 낮다.

 

우선 순위가 높은 에이전트는 길을 찾을 때 우선 순위가 낮은 에이전트를 고려하지 않고 그냥 밀고 지나가버린다. 그리고 우선 순위가 같으면 회피하려는 노력은 하지만 여의치 않을 때는 그냥 밀고 지나가게 된다. 마지막으로 낮은 우선 순위의 에이전트는 높은 우선 순위의 에이전트를 밀어내지 못한다.

 

Path Finding

 

Auto Repath

 

Auto Repath는 내비게이션 메시에 변동이 생겼을 때 자동으로 길을 다시 찾을 것인가를 설정하는 프로퍼티이다. 목적지로 가는 최단 경로의 중간이 막히면 자동으로 경로를 다시 계산해서 이동한다.

 

하지만 아주 먼거리를 이동할 때 아직 시야에 보이지 않는 중간이 막혀도 경로를 바로 재계산하기 때문에 경로가 막힌 구역까지 도착한 다음 경로를 새로 계산하기를 원한다면 체크를 해제하고 경로가 막힌 구역까지 도착한 다음 경로를 새로 계산하는 기능을 직접 구현해야 한다.

 

Area Mask

 

Area Mask에서는 이 에이전트가 지나갈 수 있는 영역과 지나가지 못하는 영역을 설정할 수 있다. 

 

특정 영역을 꺼주면 이 캐릭터는 아무리 가까운 거리라도 그 영역을 건너지 못하게 된다.

 

 

NavMeshObstacle

 

 

컴포넌트의 이름에서도 알 수 있지만 이 컴포넌트는 장애물 역할을 한다. 기본 상태에서는 작은 장애물에만 자연스러운 움직임을 보이고 큰 장애물은 부자연스럽게 회피하는 동작을 보이게 된다.

 

작은 장애물만 회피가 가능하면 그냥 Navigation Static으로 설정한 벽을 배치하는게 더 나을 것이라고 생각할 수 있다. 하지만 Navigation Static이 적용된 지형과 NavMeshObstacle은 큰 차이점이 있는데 Navigation Static으로 설정된 벽은 움직일 수 없다는 것이다. 그와 반대로 NavMeshObstacle을 사용하는 장애물은 게임이 플레이되는 도중에 언제든지 움직일 수 있다.

 

그리고 실시간으로 에이전트를 밀어내는 동작도 가능하며 장애물에 밀려난 목적지가 있는 에이전트는 다시 원래 자리로 돌아오려는 움직임으로 보이게 된다.

 

Shape

 

먼저 Shape 프로퍼티는 장애물의 형태를 결정하는 옵션으로 Box, Capsule, 두 가지 형태를 지원한다.

 

Carve를 제외한 프로퍼티는 이 Box나 Capsule의 크기를 설정하는데 쓰인다.

 

Carve

 

 

Carve는 "파내다"라는 뜻으로 내비게이션 메시 영역을 새로 굽지 않아도 실시간으로 "파내서" 에이전트가 지나갈 수 없는 영역으로 만드는 것이다.

 

Carve를 켜서 실시간으로 내비게이션 메시를 파내게 하면 큰 장애물도 자연스럽게 회피하게 할 수 있다.

 

Move Threshold

 

Carve의 하위 프로퍼티인 Move Threshold는 최소 이동 거리를 뜻한다. Move Threshold보다 조금 움직인 것은 오브젝트가 움직이지 않은 것으로 간주하여 Carve를 새로 계산하지 않는다.

 

큐브 게임 오브젝트를 미세하게 움직일 때는 내비게이션 메시의 파인 부분이 그대로 유지되지만 Move Threshold 보다 크게 움직이면 파인 부분이 사라진다. 그리고 움직임을 정지하면 내비게이션 메시에 파인 부분이 새로 생겨난다.

 

Time To Stationary

 

Time To Stationary는 게임 오브젝트가 얼마나 정지해있으면 완전히 멈춘 것으로 판정하고 Carve를 새로 계산해서 내비게이션 메시를 파낼지를 결정하는 값이다.

 

기본 값은 0.5초 후에 새로 계산하게 되어있다. 이것을 2로 변경하고 내비게이션 탭을 활성화해서 영역이 보이게 만든 다음 장애물을 움직여보자.

 

장애물이 이동을 멈추고나면 아까보다 훨씬 시간이 많이 지난 다음에 내비게이션 메시가 파지는 것을 확인할 수 있다.

 

Carve Only Stationary

 

Carve Only Stationary는 정지된 상태에서만 내비게이션 메시를 파내도록 할 것인지를 결정하는 프로퍼티이다. 

 

기본 값은 true로 체크되어 있다. 그래서 장애물이 움직이면 파내진 구멍이 사라졌다가 정지하면 내비게이션 메시가 다시 파내진다. 하지만 Carve Only Stationary를 끄면 장애물이 움직일 때 내비게이션 메시의 파인 구멍이 실시간으로 장애물을 따라 움직인다.

 

자연스러운 움직임을 위해서는 Carve Only Stationary를 끄는게 좋지만, 물체가 움직이는 상황에서 실시간으로 내비게이션 메시에 구멍을 파내는 계산을 계속하는 것은 게임의 성능에 좋지않은 영향을 끼칠 수 있기 때문에 반드시 필요한 경우에만 이 옵션을 끄고 그 외에는 이 옵션을 사용하는게 좋다.

 

이 NavMeshObstacle은 여러가지 용도로 사용할 수 있습니다.

 

유니티 공식 문서에서 언급되듯이 천천히 움직이는 탱크 같은 곳에 사용해도 되고 특정한 트리거를 발동하면 떨어져서 길을 막는 돌무더기 같은 것에도 사용해도 됩니다.

반응형
반응형

내비게이션 시스템 (1) 

NavMesh

 

작성 기준 버전 :: 2019.2

 

[이 포스트의 내용은 유튜브 영상으로도 시청하실 수 있습니다]

 

이번 포스트에서는 유니티의 내비게이션 시스템에 대해서 알아보도록 하자.

 

 

내비게이션이라는 단어는 실생활에서도 많이 들어보았을 것이다. 어떠한 목적지까지 가는 경로를 알려주는 프로그램을 우리는 내비게이션이라고 부른다.

 

유니티에서도 어떤 한 지점에서 다른 지점으로 이동하는 길을 알려주는 역할을 하는 것이 바로 내비게이션 시스템이다. 그런데 원하는 지점까지 캐릭터를 조작해서 이동하면 될텐데 내비게이션 시스템이 왜 필요할까?

 

물론 플레이어는 캐릭터를 잘 조작해서 원하는 지점까지 이동할 수 있을 것이다. 하지만 플레이어가 조작하는 캐릭터가 아니라 AI가 조작하는 몬스터 같은 NPC는 어떨까?

 

일직선의 아무런 장애물이 없는 길이라면 AI가 조작하는 몬스터라도 무리없이 목적지까지 도착할 수 있겠지만, 벽이나 기둥, 상자 같은 장애물이 가득하고 구불구불한 길이라면 몬스터는 장애물에 막혀서 제대로 목적지에 도착하지 못할 것이다.

 

내비게이션 시스템은 바로 이렇게 장애물이 가득한 환경에서 AI가 최단 경로를 찾아서 목적지에 도달하는 것을 도와주기 위해서 필요한 것이다.

 

그럼 이제 본격적으로 유니티의 내비게이션 시스템에 대해서 이야기해보자.

 

유니티의 내비게이션 시스템은 기본적으로 NavMesh, NavMeshAgent, NavMeshObstacle. 이 세 가지 요소로 이루어집니다.

 

NavMesh

 

이번 포스트에서는 먼저 NavMesh에 대해서 살펴보자.

 

 

하이어라키 뷰에 우클릭하고 [3D Object > Plane]을 선택해서 평면을 하나 만들고 크기를 x는 3, z는 10으로 설정한다. 그러면 적당히 캐릭터가 움직일 만한 바닥이 만들어진다.

 

 

이 다음에는 상단 메뉴바에서 [Window > AI > Navigation]을 선택하면 내비게이션 뷰가 열린다.

 

 

내비게이션 뷰에는 Agent, Area, Bake, Object, 이렇게 네 개의 탭이 있다.

 

Object 탭

 

이 중에서 일단 Object 탭을 먼저 살펴보도록 하자.

 

Object 탭에서는 제일 상단에 Scene Filter를 볼 수 있는데 필터의 종류로는 All, Mesh Renderer, Terrains가 있다.

 

우선 All 필터는 씬에 있는 모든 오브젝트를 보여주는 필터다. 

 

그리고 Mesh Renderer 필터는 Plane처럼 Mesh Renderer 컴포넌트를 가지고 있는 게임 오브젝트만을 보여주도록 하는 필터다.

 

마지막 Terrains 필터는 유니티 엔진에서 거대한 평면에 직접 높낮이를 조절하면서 지형을 만들 수 있는 터레인 오브젝트만을 보여주도록 하는 것이다.

 

터레인이 아니거나 메시 렌더러(Mesh Renderer) 컴포넌트를 가지지 않은 게임 오브젝트를 선택하면 메시 렌더러를 가진 게임 오브젝트나 터레인을 선택해 달라는 문구가 표시된다.

 

 

배치한 Plane을 선택하면 Navigation Static을 체크할 수 있는 체크박스와 함께 다른 옵션들이 나온다. 한마디로 터레인이나 메시 렌더러 컴포넌트를 가진 게임 오브젝트만 캐릭터가 돌아다닐 수 있는 내비게이션 영역으로 설정할 수 있다는 뜻이다.

 

여기서 Navigation Static을 체크해보면 아래 쪽의 옵션들도 활성화되는 것을 볼 수 있다. Navigation Static을 체크하면 해당 메시를 캐릭터가 길을 찾을 수 있는 표면으로 설정된다.

 

우선은 아래 쪽의 두 항목은 나중에 알아보도록 하고 넘겨두도록 하자.

 

Bake 탭

 

 

Bake 탭에는 원기둥 그림과 함께 다양한 옵션들이 보이지만 그보다 먼저 제일 아래에 이 탭의 주인공처럼 보이는 Bake 버튼을 눌러보자.

 

 

Bake 버튼을 누르면 씬 뷰에서 Plane 위에 파란색 영역이 생겨난 것을 볼 수 있다. 이게 바로 캐릭터가 길을 찾아서 이동할 수 있는 영역을 의미하는 NavMesh이다.

 

참고로 Bake는 빵이나 과자같은 것을 굽는다는 뜻을 가지고 있다. 그래서 이렇게 NavMesh를 만드는 작업 역시 "NavMesh를 굽는다"라고 표현한다.

 

 

캐릭터가 돌아다닐 NavMesh를 만들기는 했지만 아무 장애물도 없어서 너무 밋밋해보이기 때문에 몇 가지 장애물을 설치해보자. 그리고 새로 만든 장애물 역시 Object 탭에서 Navigation Static으로 설정해준 뒤, Bake 탭에서 NavMesh를 구워보자.

 

 

그러면 완전히 평면이었던 파란색 영역이 배치한 장애물을 따라서 여러 면으로 쪼개지는 것을 볼 수 있다.

 

Mesh라는 단어는 3D에서는 삼각형이나 다각형 여러 개로 면을 구성하는 것을 의미한다. NavMesh는 다각형 여러 개로 캐릭터가 이동할 수 있는 표면을 구성하는 것이다. 이 면들을 이용해서 캐릭터가 찾아갈 길을 찾아내는 것이다.

 

그럼 이제부터 Bake 탭의 주요 옵션들을 하나씩 알아보도록 하자.

 

Agent Radius

 

Agent는 내비게이션 메시 위에서 움직이는 대상을 의미한다. 즉 Agent Radius는 NavMesh 위에서 움직일 대상의 반지름이다.

 

 

이 값을 1로 변경하고 NavMesh를 새로 구워보면 내비게이션 메시의 비어있는 경계 부분이 넓어지는 것을 볼 수 있다. 이것은 NavMesh 위를 돌아다닐 Agent의 Radius가 증가해서 뚱뚱해졌기 때문에 벽에 바짝 붙어서 움직일 수 없기 때문에 이렇게 된 것이다.

 

Agent Radius를 원상복구하고 NavMesh를 다시 구워보면 날씬해진 Agent가 돌아다닐 수 있는 범위가 증가한다.

 

Agent Height

 

Agent Height = 2
Agent Height = 1
Agent Height = 4

 

 Agent Height를 Agent의 키를 의미한다.

 

오르막길 아래의 작은 길을 보면서 Height를 1로 변경하면 Agent의 작아진 높이 때문에 통과할 수 있는 범위가 늘어나는 것을 볼 수 있다. 반대로 Height를 4로 변경하면 오르막길 아래의 샛길로 이동하지 못하게 된다.

 

Max Slope

 

Max Slope 값은 NavMesh에 이동할 수 있는 길로 포함될 수 있는 경사로의 최대 각도를 의미한다.

 

여기 맵에 배치된 경사로의 각도는 25도이다. 그리고 Bake 옵션의 최대 경사로 각도의 기본값은 45도이다.

 

 

그렇기 때문에 NavMesh를 구울 때 이 경사로가 이동할 수 있는 지역으로 포함된 것이다.

 

 

만약 MaxSlope 값을 25도보다 작은 20도로 변경하고 다시 구우면 이 경사로가 이동할 수 없는 지역이 되는 것을 볼 수 있다.

 

Step Height

 

그 다음 Step Height는 Agent가 가벼운 계단 정도로 여기고 올라갈 수 있는 단의 높이를 의미한다. 기본 값은 0.4로 설정되어 있다.

 

 

맵에 낮은 단으로 설치된 오브젝트의 높이는 0.25로 Step Height가 이보다 크기 때문에 이 단 역시 NavMesh로 연결되어 있다.

 

 

Step Height를 0.1로 변경하고 내비게이션 메시를 구워보면 연결된 NavMesh가 끊어져서 이동할 수 없는 지역이 되는 것을 볼 수 있다.

 

이렇게 Agent Radius, Agent Height, Max Slope, Step Height를 이용해서 내비게이션 메시의 영역을 설정할 수 있다.

 

Area 탭

 

 

Area 탭에서는 사용자가 필요한 내비게이션 메시 구역을 설정하고 그 구역을 지나가는 비용을 설정할 수 있다. 기본 Area로는 Walkable, Not Walkable, Jump. 이렇게 세 가지가 있다.

 

 

User3 위치에 Water를 추가하고 비용을 3으로 설정해보자.

 

 

그리고 맵에 추가적인 구조물을 몇 개 더 설치해보자. 이렇게 다른 쪽으로 넘어가는 두 갈래 길을 만들었다.

 

한 쪽은 바닥이 내려간 길이고 다른 한 쪽은 바닥이 올라간 다리 같은 길이다.

 

먼저 제일 낮은 바닥 부분을 제외한 구역을 선택해서 Navigation Static을 체크하고 Area는 Walkable으로 둔다. 그 다음에는 바닥을 선택해서 Navigation Static을 체크하고 Area를 Water로 설정한 다음 NavMesh를 구워보자.

 

 

그러면 다른 구역은 전부 같은 파란색으로 영역이 지정되지만 가장 낮은 바닥만 다른 색으로 지정된다.

 

반대편으로 넘어가는 블록 한 칸의 이동 비용을 1이라고 가정했을 때, 여기서 건너편으로 건너가기로 결정했을 때 이 다리를 건너는 비용은 3이고, Water로 지정된 바닥을 건너는 비용은 5이기 때문에 위로 건너는 방법이나 아래로 건너는 방법이나 이동 거리 자체는 같지만, Agent는 가급적이면 이 다리 쪽 경로를 선택하려고 할 것이다.

 

이렇게 Area마다 다른 비용을 책정해서 내비게이션 메시를 잘 구성하면 길은 쉽지만 몬스터가 자주 돌아다니는 구역과 몬스터는 자주 오지 않지만 함정이 많은 구역처럼 좀 더 다양한 레벨 디자인을 손쉽게 구성할 수 있을 것이다.

 

Agents 탭

 

 

Agents 탭에는 Bake 탭에서 본 것과 같은 그림과 옵션들이 있다. 다만 Humanoid라는 기본 타입과 함께 새로운 타입을 추가할 수 있다.

 

덩치가 큰 에이전트와 덩치가 작은 에이전트를 만들어서 덩치가 작은 에이전트는 지나갈 수 있는 곳을 덩치가 큰 에이전트는 돌아서 가야되게 만들 수 있다.

 

반응형
반응형

Vector 

좌표와 속도를 다루기 위한 도구

 

작성 기준 버전 :: 2019.2

 

[유튜브 영상에서도 본 포스트의 내용을 시청하실 수 있습니다.]

 

이번 섹션에서는 유니티 엔진의 벡터에 대해서 알아보자.

 

게임 속에 존재하는 모든 오브젝트들은 어느 위치에 존재하거나, 어딘가를 향해서 이동한다. 아무것도 움직이지 않는 게임은 거의 존재하지 않는다. 그렇기 때문에 이렇게 오브젝트의 위치와 이동 등에 대해서 다루는 도구가 필요한데, 그것을 위한 도구가 바로 벡터이다.

 

벡터에 관한 이번 포스트를 읽기 전에 유니티의 좌표계에 대한 글을 읽어보는 것도 좋다.

 

벡터(Vector)

 

벡터에 대해서 수학이나 물리학에서는 여러 복잡한 정의가 존재하는데 간단하게 요약하자면 특정한 공간에서의 방향과 크기를 표현하는 도구로서 주로 화살표로 표시되는 개념이다.

 

[그림 1]

 

[그림 1]을 예시로 들면 오른쪽으로 뻗어나가는 X축과 위쪽으로 뻗어나가는 Y축, 두 개의 축으로 구성된 2차원 평면 공간이 있고, (2, 2) 위치를 가리키고 있는 V1 벡터와 (-1, -2) 위치를 가리키고 있는 V2 벡터, 두 개의 벡터가 2차원 공간 속에 존재하는 것을 볼 수 있다.

 

즉, 여기서는 2차원 평면이 "특정한 공간"이며, 벡터는 그 공간 안에서 방향과 크기를 표현하는 도구라고 말했듯이, 벡터를 표시한 화살표를 보는 것만으로도 이 벡터가 어느 방향을 가리키고 있고 얼마만큼의 길이를 가지는지 알 수 있다.

 

그리고 이 "특정한 공간"은 몇 차원이든 가능하지만 대부분은 사람이 쉽게 인지할 수 있는 2차원 혹은 3차원으로 정의된다. 유니티에서도 2차원과 3차원의 벡터만 사용한다.

 

벡터의 활용

 

벡터는 방향과 크기를 표현하는 도구라고 이야기했는데, 이것을 이용해 여러 가지 용도로 활용된다.

 

첫 번째 활용법은 방향이다. [그림 1]과 같이 평면에 벡터가 표시하는 좌표까지 화살표를 그리는 것으로 방향을 쉽게 알 수 있다.

 

[그림 2]

 

두 번째 활용법은 속도이다. V1과 V2가 [그림 1]에서는 서로 다른 방향을 가리키고 있는데, [그림 2]와 같이 두 벡터를 같은 방향으로 놓고 보면, V1이 V2보다 긴 것을 확인할 수 있다. 1초 동안 각 벡터의 길이만큼 이동한다고 가정하면, 당연히 같은 시간동안 V1만큼 이동한 것이 V2만큼 이동한 것보다 멀리 이동할 수 있고, 벡터의 방향 자체가 이동 방향의 의미를 가지기 때문에, 이동하고자하는 방향과 속력, 즉, 속도의 개념으로 활용되는 것이다.

 

세 번째 활용법은 좌표이다. [그림 1]에서 X축과 Y축이 교차하는 지점을 공간의 중심이라고 가정했을 때, V1 위치에 어떤 오브젝트가 있다면, 그 오브젝트는 공간의 중심으로부터 (2, 2)의 위치에 있다고 말할 수 있다.

 

벡터의 계산

 

벡터에 대한 여러가지 계산들이 존재하는데 이러한 계산 방법들을 잘 활용하면 게임의 기능을 구현하는데 유용하게 사용할 수 있다.

 

벡터의 덧셈과 뺄셈

 

두 개의 벡터는 서로 더하거나 뺄 수 있다.

 

[그림 3]

 

우선 벡터의 덧셈을 살펴보자. [그림 3]을 보면 (1, 2)의 V1과 (2, 1)의 V2를 더하면 (3, 3)의 V3가 나오는 것을 볼수 있다. V1 지점에서 V2 만큼 이동했다고 여기면 된다.

 

[그림 4]

 

또 다른 관점에서 살펴보면 두 벡터의 합은 서로 다른 방향의 두 힘이 충돌했을 때의 그 합쳐진 힘의 진행 방향으로 해석될 수도 있다.

 

[그림 5]

 

벡터의 뺄셈은 역시 (1, 2)인 V1에서 (2, 1)인 V2를 빼면 (-1, 1)인 V3가 나온다. 다만 여기서 기억할 점은 이렇게 결과 값으로 나온 V3가 V2 지점에서 시작하여 V1 방향으로 이동하는 V3'와 길이와 방향이 모두 같다는 것이다. 이것을 이용하면 V1과 V2 사이의 거리, V2에서 V1으로 가는 방향등을 구할 수 있다.

 

벡터와 스칼라의 곱셈

 

벡터는 좌표로서 공간 상에서 방향과 크기를 의미하지만 스칼라는 크기 만을 가지는 값이다. 벡터가 차원 축을 따라서 (2, 0), (1, 2, 3)과 같은 값을 가지는 것에 비해 1, 10, 24 등의 단일한 값을 의미한다.

 

[그림 6]

 

(1, 1)인 V1에 4인 스칼라 S를 곱하면 V1의 각 원소에 S를 곱하여 (4, 4)인 V2를 얻게 된다. 이렇게 벡터에 스칼라를 곱하는 계산은 주로 벡터의 크기를 원하는대로 늘이거나 줄이는 등의 계산이나, 벡터에 -1을 곱해서 현재 벡터의 반대 방향을 구하는데 주로 사용된다.

 

벡터의 길이

 

[그림 2]에서는 벡터를 나란히 놓는 원시적인 방식으로 벡터의 길이를 비교했다. 이런 방식 외에 계산적인 방식으로도 벡터의 길이를 구할 수 있다.

 

 

벡터의 길이를 구하는 공식은 위와 같다. 벡터의 각 원소를 제곱한 뒤, 모두 더하여 제곱근을 구하면, 벡터의 길이가 나온다.

 

[그림 1]

 

다시 [그림 1]을 보자. V1의 좌표는 (2, 2)이다. 이것을 공식에 대입하면 : 

 

 

위와 같은 값이 나온다. 이것은 사실 피타고라스의 정리에서 유도된 빗변의 길이를 구하는 공식이다. 벡터는 항상 각 축을 대상으로 직각을 이루는 직각 삼각형의 형태이기 때문에 이 공식으로 길이를 구할 수 있는 것이다.

 

벡터의 길이는 즉, 거리로, 벡터의 뺄셈을 이용하면 두 벡터 간의 거리를 구할 수 있다.

 

 

3차원 벡터에 대한 공식은 2차원 공식에 z축 좌표를 추가해서 계산하면 된다.

 

벡터의 정규화(Normalize)

 

벡터의 정규화는 현재 벡터의 방향을 유지한 채로 벡터의 길이를 1로 만드는 것을 의미하며, 이를 단위 벡터라고 부른다.

 

 

단위 벡터를 구하려면 벡터의 각 원소를 벡터의 길이로 나누어 주면 된다. 예를 들어 [그림 1]의 V1을 단위 벡터로 만들려면 V1의 각 원소 (2, 2)를 각각 벡터의 길이인 2.828427로 나누어주면 된다. 그러면 각 원소의 값은 (0.707106..., 0.707106...)이 된다. 이렇게 나온 단위 벡터에 대해서 다시 벡터의 길이를 구해보면 1의 근사값이 나올 것이다.

 

이런 단위벡터는 정확히 벡터의 방향만을 추출하고자 할 때 사용되는데, 주 사용처를 이야기 해보자면, 만약 캐릭터를 마우스의 방향으로 이동시키려고 할 때, (마우스 위치) - (캐릭터 위치)로 캐릭터에서 마우스 위치 방향을 찾아낼 것이다. 그런데 이 벡터를 그대로 사용하면 마우스의 거리가 멀어지면 멀어질 수록 이 이동 벡터의 길이가 길어지기 때문에 마우스와 캐릭터의 거리가 멀면 캐릭터가 빨라지고 가까워지면 캐릭터가 느려지는 문제가 발생할 것이다.

 

(마우스 위치) - (캐릭터 위치)로 찾아낸 방향을 정규화해서 단위 벡터로 만든 다음에 캐릭터의 이동 속도만 곱해주면 캐릭터가 일정한 속도로 이동한다.

 

벡터의 내적(Dot Product)

 

점곱(dot product), 내적(inner product)이라고 부르는 계산으로 계산 결과 값으로 벡터가 아닌 단일 값, 즉 스칼라 값을 내는 계산이다. 때문에 스칼라 곱이라고도 부르는데, 벡터와 스칼라의 곱셈과 헷갈려서는 안된다.

 

 

계산 공식은 위와 같다. 벡터의 각 원소끼리 곱한 뒤, 모두 더하는 것으로 벡터의 내적을 구할 수 있다.

 

이렇게 나온 계산 결과의 의미는 내적의 값이 0이면 두 벡터의 각이 90도이고, 0보다 크면 두 벡터 사이의 각도가 90도보다 작고, 0보다 작으면 각도가 90도보다 크다는 의미이다. 여기에 삼각함수를 이용하면 두 벡터 사이의 각도를 구할 수 있다.

 

벡터의 외적(Cross Product)

 

가위곱(cross product), 외적(outer product)이라고 부르는 계산으로 두 벡터와 모두 직교하는, 즉 두 벡터와의 각이 모두 90도를 이루는 벡터를 결과값으로 내며, 3차원 공간에서만 성립하는 계산이다.

 

 

외적의 계산 공식은 위와 같다. 

 

[그림 7]

 

 V1과 V2에 대해서 직교하는 벡터는 V3, V4 둘 다 될 수 있는데, 이 결과는 왼손 좌표계를 사용하느냐, 오른손 좌표계를 사용하느냐에 따라 결과가 달라진다. 왼손 좌표계에서 V2 X V1의 결과값은 V3로 나오고 오른손 좌표계에서는 V4로 나온다. 이렇게 나온 벡터를 법선 벡터(Normal Vector)라고 부른다.

 

[그림 8]

 

그래서 벡터의 외적은 [그림 8]과 같이 한 면이 바라보는 방향을 구하는 용도로 주로 사용된다.

 

 

 

 

유니티 엔진의 벡터

 

그러면 이제 유니티 엔진에서의 벡터에 대해서 알아보자.

 

Vector2 vector2 = new Vector2();

 

vector2.x = 1f;

vector2.y = 1f;

 

Vector3 vector3 = new Vector3();

 

vector3.x = 1f;

vector3.y = 1f;

vector3.z = 1f;

 

위의 코드 예시는 유니티에서 사용되는 Vector2 구조체와 Vector3 구조체이다. Vector2 구조체는 2차원 평면 공간에 속하는 벡터로 X축의 좌표를 표시하기 위한 x 변수와, Y축의 값을 표시하기 위한 y 변수를 가진다. Vector3 클래스는 여기에 더해 Z축을 표시하는 z 변수까지 가진다.

 

Vector2는 대부분 UI 같은 2D 공간이나 2D 게임을 제작할 때 사용되고, Vector3는 일반적인 3D 공간에서 사용된다.

 

자, 그렇다면 우리는 벡터와 관련된 기능을 전부 직접 구현해서 사용해야 할까? 아니다. 유니티에서는 이러한 벡터와 관련된 기능들을 모두 제공한다.

 

벡터의 덧셈과 뺄셈

 

Vector3 v1 = new Vector3(1f, 2f, 0f);

Vector3 v2 = new Vector3(2f, 1f, 0f);

// 벡터의 덧셈

Debug.Log("v1 + v2 = " + (v1 + v2));

// 벡터의 뺄셈

Debug.Log("v1 - v2 = " + (v1 - v2));

 

 

벡터의 덧셈과 뺄셈은 간단하게 일반 덧셈과 뺄셈을 하듯이 연산자를 사용하면 바로 구할 수 있다.

 

벡터와 스칼라의 곱셈

 

// 벡터와 스칼라의 곱셈

Vector3 v1 = new Vector3(1f, 1f, 0f);

int scalar = 4;

Debug.Log("v1 * scalar = " + (v1 * scalar));

 

 

벡터와 스칼라, 단일 정수 혹은 단일 실수와의 곱셈 역시 일반 계산과 같이 간단하다.

 

벡터의 길이

 

Vector3 v1 = new Vector3(2f, 2f, 0f);

// 벡터의 길이

Debug.Log("length of v1 = " + (v1.magnitude));

 

 

벡터의 길이는 Vector3 구조체에 포함되어 있는 magnitude 프로퍼티를 통해서 가져올 수 있다. 이것은 Vector2에서도 똑같다.

 

벡터의 정규화

 

Vector3 v1 = new Vector3(2f, 2f, 0f);

// 정규화된 단위 벡터

Vector3 normalizedVector = v1.normalized;

Debug.Log("||v1|| = " + normalizedVector);

// 단위 벡터의 길이 확인

Debug.Log("length of ||v1|| = " + normalizedVector.magnitude);

 

 

Vector3 구조체의 normalized 프로퍼티를 이용하면 정규화된 단위 벡터를 가져올 수 있다. magnitude 프로퍼티를 다시 사용해보면 단위 벡터의 길이가 1임을 확인할 수 있다.

 

벡터의 내적

 

[그림 9]

 

아래 코드 예시에 정의된 각 벡터는 [그림 9]와 같다.

 

Vector3 v1 = new Vector3(2f, 0f, 0f);

Vector3 v45 = new Vector3(1f, 1f, 0f);

Vector3 v90 = new Vector3(0f, 2f, 0f);

Vector3 v135 = new Vector3(-1f, 1f, 0f);

 

// 벡터의 내적

Debug.Log("v1 . v45 = " + Vector3.Dot(v1, v45));

Debug.Log("v1 . v90 = " + Vector3.Dot(v1, v90));

Debug.Log("v1 . v135 = " + Vector3.Dot(v1, v135));

 

// 두 벡터 사이의 각도

Debug.Log("v1 . v45 = " + Vector3.Angle(v1, v45));

Debug.Log("v1 . v90 = " + Vector3.Angle(v1, v90));

Debug.Log("v1 . v135 = " + Vector3.Angle(v1, v135));

 

 

벡터의 내적을 구하려면 Vector3 클래스의 정적 함수인 Dot 함수를 사용하면 된다. 벡터의 내적에 대해서 설명했듯이, v1과 v45 사이의 각도는 90도 보다 작기 때문에 0보다 큰 값이 나왔고, v1과 v90 사이 각은 정확히 90도이기 때문에 0, v1과 v135 사이 각은 90도보다 커서 0보다 작은 값이 나온 것을 확인할 수 있다.

 

덤으로 Vector3의 또 다른 정적 함수인 Angle 함수를 사용하면 두 벡터 사이의 각을 얻을 수 있다.

 

벡터의 외적

 

Vector3 v1 = new Vector3(2f, 0f, 0f);

Vector3 v2 = new Vector3(0f, 0f, 2f);

 

// 벡터의 외적

Debug.Log("v1 X v2 = " + Vector3.Cross(v1, v2));

 

 

벡터의 외적은 Vector3 클래스의 정적 함수인 Cross 함수를 통해서 구할수 있다.

 

이번 섹션에서는 벡터와 그 계산법을 알아보고 유니티 엔진에서는 어떻게 사용되는지 알아보았습니다.

반응형
  1. 료용 2020.02.03 02:14 신고

    프로그래머가 기본수학을 알아야하는이유... 유투브에 수포자를위한 프로그래머 수학보고 아 그렇구나 이러기만하고 적용을 못시키겠더라고요

    • wergia 2020.02.03 03:52 신고

      사실 저도 수포자입니다 ㅋㅋ 다만 벡터는 눈에 보이기 쉬운 개념이라 금방 배울 수 있더라구요. 벡터로 하는 작업이 조금 어려울 때는 종이에 화살표 그려보면서 하면 잘 되더라구요.

+ Recent posts