🤍ref.

  1. Unity Learn John Lemon’s Haunted Jaunt: 3D Beginner

  2. Unity Documentation

✨Unity info
본 튜토리얼 문서의 유니티 버전은 2020.3v이나, 2021.3v으로 실습 후 게시글을 작성하였습니다.



🍋적 캐릭터: 정적 관찰자

image 녹화_2022_08_25_13_26_27_307

왼쪽: 정적 관찰자 Gargoyle 오브젝트 / 오른쪽: Game view에서의 Gargoyle


1. 가시선 트리거 생성

image

적 캐릭터와 주인공 캐릭터가 충돌할 경우 이벤트가 발생해야 한다. Gargoyle 게임 오브젝트를 생성하는 것만으로는 JohnLemon을 찾아낼 수 없으므로, 트리거를 만들어 충돌 이벤트를 작성해야 한다. Gargoyle 게임 오브젝트의 자식 오브젝트로 PointOfView를 생성한다. 가고일 애니메이션을 실행했을 때 얼굴이 정면 아래를 향하고 있으므로, PointOfView가 바닥에 기울어져 있도록 위치와 기울기를 조정한다.

  • Position: (0, 1.4, 0.4)
  • Rotation: (20, 0, 0)
  • Capsule Collider 컴포넌트 추가: 트리거 생성
    • Center: (0, 0, 0.95)
    • Radius: 0.7, Height: 2
    • Direction: Z-Axis

Direction: Collider의 기준 축

  • X-Axis: 좌우 크기
  • Z-Axis: 전후 크기
  • Y-Axis: 상하 크기

image

적 캐릭터를 중심으로, 앞뒤로 기울어져 있는 Capsule Collider



2. Observer 스크립트


플레이어 감지 클래스

GameEnding 스크립트처럼 OnTriggerEnter 함수와 조건문을 통해 플레이어 감지

  • 중간에 벽이 있을 경우, JohnLemon이 트리거에서 나가야 하므로 OnTriggerExit함수 선언


가시선 확인

플레이어의 위치마다 가시선을 확인하기 위해 Update 메서드에 가시선 확인 스크립트를 작성한다.

  • Vector3 direction: 새로운 Vector3 변수 생성

    • 벡터 방향: JohnLemon 위치 - PointOfView 위치 ($A$부터 $B$까지의 벡터: $B - A$)

    • Vector3.up: JohnLemon의 질량 중심을 확인하기 위해 Vector의 방향을 1 가산

      (일반적으로 캐릭터의 위치는 두 발 사이의 지면임)

  • new Ray: 생성자를 호출해 새로운 인스턴스 생성

    • ray: 특정 지점에서 시작하는 선. 원점과 방향(direction) 필요

      한 지점에서 시작하는 선의 경로를 따라 콜라이더의 존재 여부 확인

  • if(Physics.Raycast(ray, out raycastHit))

    • Raycast: ray를 따라 콜라이더 확인. 물체와 부딪히면 true, 그렇지 않으면 false 반환. 일반적으로 조건문에 사용
      • 감지하고자 하는 콜라이더의 종류를 제한해야 함
    • out raycastHit: 메서드를 통해 값을 변경 및 설정. Raycast에 부딪히는 대상에 관한 정보로 데이터를 설정함



3. GameEnding.cs 수정

  • Update 메서드

    • 플레이어가 맵을 탈출했을 경우(m_IsPlayerAtExit): exitBackgroundImageCanvasGroup 변수 실행

    • 플레이어가 적에게 탐지됐을 경우(m_IsPlayerCaught): caughtBackgroundImageCanvasGroup 변수 실행

  • EndLevel메서드

    • doRestarttrue라면 씬을 다시 Load시켜 처음 화면으로 돌아감


m_IsPlayerCaught 변수 설정

m_IsPlayerCaught 변수는 트리거를 위해 클래스 외부에서 설정되어야 한다. 단, 모든 클래스가 m_IsPlayerCaught 변수를 확인할 필요가 없으므로 public으로 설정하는 것은 바람직하지 않다. 따라서, 해당 변수의 접근을 제한하고 참으로 설정해주는 메서드를 선언해 플레이어가 적에게 잡혔을 때만 다른 클래스가 감지할 수 있도록 한다.

  • Observer 스크립트 내 Update 메서드의 마지막 조건문에 gameEnding.CaughtPlayer(); 코드 추가


image

Observer의 Player 필드에는 JohnLemon 오브젝트를, Game Ending 필드에는 GameEnding 오브젝트를 할당한다.


ezgif com-gif-maker (5)

결과 화면



🍋적 캐릭터: 동적 관찰자

image 녹화_2022_08_25_13_28_55_415

왼쪽: 동적 관찰자 Ghost 오브젝트 / 오른쪽: Game view에서의 Ghost



1. 유령 관찰자 생성

Kinematic Rigidbody

image

  • Kinematic Rigidbody: 게임 오브젝트와 충돌할 수 있지만, 그 힘의 영향은 받지 않을 경우 체크


유령과 충돌 이벤트 생성

image

Gargoyle 오브젝트의 자식 오브젝트인 PointOfView를 Project view의 Prefabs으로 드래그해 프리팹화한다. PointOfView 프리팹을 Ghost의 자식 오브젝트로 할당해 일괄적으로 추적 대상을 업데이트할 수 있다.



2. Nav Mesh Agent

유령이 게임 맵 내부를 돌아다닐 수 있도록 Nav Mesh Agent 컴포넌트를 사용한다.

필요한 컴포넌트

  1. Nav Mesh Agent

  2. Nav Mesh Agent 이동 스크립트


image

  • Ghost 오브젝트와 Nav Mesh Agent 컴포넌트의 둘레가 맞도록 Radius 프로퍼티 조정 (0.25)
  • Stopping Distance: 게임 오브젝트가 도착지부터 해당 거리까지의 영역에서 감속


image

Nav Mesh Agent 컴포넌트를 추가한 후의 Ghost 오브젝트



3. WaypointPatrol.cs

스크립트가 NavMeshAgent 클래스에 접근할 수 있도록 using UnityEngine.AI 코드를 추가한다.

  • NavMeshAgent: 인스펙터 창에서 Nav Mesh Agent 레퍼런스 할당
  • Transform[] waypoints: Ghost 오브젝트가 이동할 지점. 웨이포인트의 개수를 유연하게 조절하도록 배열 사용
    • navMeshAgent.SetDestination: Nav Mesh Agent의 최초 위치가 될 웨이포인트
  • if(remainingDistance < stoppingDistance): 목적지까지 남은 거리가 Stopping Distance보다 짧은지 확인
    • 웨이포인트 개수와 인덱스+1이 일치할 경우 웨이포인트 인덱스를 0으로 설정 (유령 순환이동 기능)


왜 Vector3 변수 대신 waypoint를 사용할까?

유령이 순회하는 웨이포인트를 Vector3으로 만들 경우, 오브젝트가 이동할 모든 위치를 수동으로 설정해야 하며, 위치로 할당하는 값이 정확하지 않을 수도 있다. 따라서 게임 오브젝트에 직접적으로 레퍼런스를 부여하지 않고, Transform 컴포넌트에 대한 레퍼런스를 활용하는 것이 더 합리적이다.


image

Waypoint Patrol 스크립트의 필드에 Nav Mesh Agent 컴포넌트와 Waypoint 오브젝트를 부여해 Ghost 오브젝트가 두 웨이포인트 사이를 이동할 수 있도록 한다.

image

image

Waypoint와 Waypoint(1)의 position


ezgif com-gif-maker (6)

결과 화면

4. Hierarchy 정리

image

빈 게임 오브젝트의 자식 오브젝트로 비슷한 유형의 오브젝트들을 넣어 Hierarchy view를 정리할 수 있다.

Leave a comment