지난번에 이어 게임을 만들어보자.
이번에 참고할 강의는 아래 강의이다.
https://www.youtube.com/watch?v=UnPZyFjUvOM&list=PLctzObGsrjfyevwpeEVQ9pxGVwZtS7gZK&index=4
이번 강의에서는 적을 만들어본다.
시작해보자.
먼저 적으로 사용할 캡슐을 하나 만든다.
적에 적용할 마테리얼 Enemy 도 만들어서 적용해주자.
Enemy 스크립트도 만들어서 Enemy 오브젝트에 추가해주자.
게임을 플레이 할 때 만나는 적을 보면 적이 나를 공격하러 따라온다.
이렇게 적이 나를 따라오는 기능을 유니티의 내비메쉬(NavMesh) 시스템으로 구현 할 것이다.
(자세한 설명 : https://docs.unity3d.com/kr/2021.3/Manual/nav-NavigationSystem.html)
구현을 하려면 창 > AI > 내비게이션 으로 내비게이션 창을 열어야 하는데..
창(Window)탭을 열면 AI > 내비게이션이 없다 ..?
찾아보니 패키지 설치가 안된 것 같다..
창 > 패키지 관리자 를 통해 AI Navigation 을 설치하자..
다운받고 창을 열었다.
바닥인 Plane 을 선택하고,
내비게이션 창에서 Navigation Static 을 선택하고, Walkable 로 설정하자.
그리고 베이크 탭을 눌러 Bake 해주면 캐릭터가 걸을 수 있는 푸른색 영역이 생성된다.
적이 장애물을 피해 잘 오는지 확인하기 위해 장애물을 만들어보자.
Obstacle 이라는 큐브를 생성하자.
마테리얼을 만들어 적용시켜 색을 조정해주고 위치를 조정하자.
이제 내비게이션 창에서 스태틱으로 설정 후 Not Walkable 로 설정해
걸어 갈 수 없게 설정해주고 Bake 하자.
그러면
위와 같이 걸어갈 수 있는 영역이 장애물 주위로 잘려나가서
걸을 수 없는 영역이 되었다.
이제 적에게 NavMesh 를 적용해 내비게이션을 적용해보자.
Enemy 오브젝트를 클릭하고 컴포넌트에서
내비 메시 에이전트(Nav Mesh Agent)를 클릭해 추가한다.
이제 만들어둔 Enemy 스크립트를 작성해 내비게이션을 설정하자.
| Enemy 스크립트
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(UnityEngine.AI.NavMeshAgent))]
// 현재 오브젝트에 NavMeshAgent 를 포함
public class Enemy : MonoBehaviour
{
UnityEngine.AI.NavMeshAgent pathfinder; // 내비게이션 레퍼런스
Transform target; // 적의 타겟(플레이어) 트랜스폼
void Start()
{
pathfinder = GetComponent<UnityEngine.AI.NavMeshAgent>();
// NavMeshAgent 레퍼런스 생성
target = GameObject.FindGameObjectWithTag("Player").transform;
// 타겟으로 "Player" 라는 태그를 가진 오브젝트의 트랜스폼을 저장
StartCoroutine(UpdatePath());
// 지정된 시간마다 목적지 쪽으로 위치를 갱신하는 코루틴 실행
}
void Update()
{
}
IEnumerator UpdatePath()
// 해당 코루틴 실행 시 지정한 시간마다 루프문 내부 코드 반복
{
float refreshRate = .25f; // 루프 시간
while(target != null) // 타겟이 있을 때 반복
{
Vector3 targetPosition = new Vector3(target.position.x, 0, target.position.z);
// 타겟의 x, z 좌표만 가져와 벡터로 저장
pathfinder.SetDestination(targetPosition);
// 내비게이션의 목적지를 타겟(플레이어)의 위치로 설정
yield return new WaitForSeconds(refreshRate);
// refreshRate 시간만큼 기다림
}
}
}
Update 함수를 통해 적의 위치를 갱신하는 방법도 있다.
하지만 연산 횟수를 볼 때 매우 비효율적이다.
1초에 60프레임인 컴퓨터의 경우 1초에 적의 위치가 60번 갱신된다.
하지만 위에서 처럼 코루틴을 통해 타이머 형식으로 위치를 갱신하여
지정한 시간에 위치를 갱신하여 연산 횟수를 줄여 컴퓨터의 부담을 줄일 수 있다.
이제 게임을 한번 실행해보자.
위와 같이 잘 따라오는 것을 볼 수 있다.
아직 총을 쏴도 적이 아무런 반응이 없다.
총알이 적에게 맞으면 데미지가 들어가도록 해보자.
일단 먼저 총알에 충돌 감지 기능을 넣자.
발사체에서 레이캐스트를 사용하여 발사체가 지정한 물체에 충돌하였는지 확인하자.
| Projrctile 스크립트
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Projectile : MonoBehaviour
{
public LayerMask collisionMask;
// 어떤 오브젝트, 레이어가 발사체(총알)과 충돌할지 저장.
float speed = 10.0f; // 기본 속도
public void SetSpeed(float newSpeed) // 속도 설정 메소드
{
speed = newSpeed; // 입력받은 속도로 설정
}
void Update()
{
float moveDistance = speed * Time.deltaTime; // 총알의 이동 거리
CheckCollision(moveDistance); // 총알 충돌 확인 메소드 호출
transform.Translate(Vector3.forward * Time.deltaTime * speed);
// 총알 이동
}
void CheckCollision(float moveDistance) // 총알 충돌 확인 메소드
{
Ray ray = new Ray(transform.position, transform.forward);
// 레이 생성, 발사체(총알)위치와 정면 방향을 전달.
RaycastHit hit; // 충돌 오브젝트 반환 정보
if (Physics.Raycast(ray, out hit, moveDistance, collisionMask, QueryTriggerInteraction.Collide))
/* 레이캐스트로 발사체가 오브젝트나 레이어에 닿았는지 확인.
QueryTriggerInteraction 을 Collide 로 하여 트리거 콜라이더와 충돌 하게 설정. */
{
OnHitObject(hit); // 충돌 처리 메소드 호출
}
}
void OnHitObject(RaycastHit hit) // 충돌 시 처리 메소드
{
print(hit.collider.gameObject.name); // 충돌 시 콘솔에 출력
GameObject.Destroy(gameObject); // 현재 오브젝트(발사체) 제거
}
}
위 코드 작성 후 적 오브젝트의 트리거를 활성화 하여
트리거 콜라이더로 만들고, 레이어를 설정해주자.
트리거를 활성화.
실행 시 이전에는 적이 플레이어를 밀어냈지만 이제 플레이어와 겹쳐져 밀리지 않는다.
맨 위의 레이어에서 추가하기를 누른다.
새로운 레이어 Enemy 를 만들어주자.
새로 만든 Enemy 레이어를 선택해준다.
이제 Projectile 스크립트가 적용되어있는 Bullet 프리팹으로 와서
스크립트의 Collision Mask 에 Enemy 를 할당해준다.
이제 실행해보자.
위와 같이 적에게 총알이 맞으면 콘솔 창에 오브젝트 이름이 출력되고,
총알이 사라진다.
이렇게 총알의 충돌 감지까지 완료했다.
다음 강의에서 적에게 총알 충돌 시 데미지를 주도록 해보자.
'Unity > 게임개발' 카테고리의 다른 글
[Unity] 게임 개발 일지 | 탑다운 슈팅 6 (0) | 2023.11.24 |
---|---|
[Unity] 게임 개발 일지 | 탑다운 슈팅 5 (1) | 2023.11.23 |
[Unity] 게임 개발 일지 | 탑다운 슈팅 4 (0) | 2023.11.22 |
[Unity] 게임 개발 일지 | 탑다운 슈팅 2 (0) | 2023.11.17 |
[Unity] 게임 개발 일지 | 탑다운 슈팅 1 (0) | 2023.11.16 |