[SnowFight] 몬스터 만들기 (NavMeshAgent)
플레이어를 따라오는 몬스터를 구현해보겠습니다. NavMeshAgent 컴포넌트는 내비메시 데이터를 기반으로 목적지까지 최단 거리를 계산하여 이동합니다. Bake를 하는 과정에서 장애물과 같은 다른
stotop.tistory.com
첫번째 게시글에 이어서 몬스터에 관련된 스크립트 입니다.
1. 몬스터 상태에 관한 스크립트 입니다.
몬스터의 상태를 4가지로 분류하였습니다.
IDLE (가만히 있기), TRACE (쫓기), ATTACK (공격), DIE (죽음)
몬스터에 스크립트를 추가하고 인스펙터창에서 확인합니다.
IDLE을 기본으로 설정합니다.
enum 열거형에 작성하였던 4가지 모두가 있는걸 볼 수 있습니다.
// 몬스터들의 다양한 상태들을 Enum으로 만들어 놓습니다.
public enum MonsterState
{
IDLE, TRACE, ATTACK, DIE
}
// 몬스터의 현재상태입니다. (가만히 있기)
public MonsterState state = MonsterState.IDLE;
// 쫓는 사정거리를 지정합니다.
public float traceDis = 8.0f;
// 공격 사정거리를 지정합니다.
public float attackDis = 2.0f;
// 몬스터의 생존여부입니다.
public bool isDie = false;
2. 몬스터의 변화를 체크하는 코루틴 함수입니다.
0.3초 간격으로 플레이어와 몬스터 사이의 거리를 측정해 몬스터의 상태를 변화시키게 하였습니다.
몬스터가 죽기전에는 While 문으로 반복하다가 몬스터가 죽게되면 끝이나게 작성하였습니다.
private Transform monsterTrans;
private Transform playerTrans;
private NavMeshAgent agent;
void Start()
{
// 몬스터의 Transform 입니다.
monsterTrans = GetComponent<Transform>();
// 몬스터가 쫓아야 하는 플레이어의 Transform 입니다.
// FindWithTag와 같은 Find 함수는 처리속도가 느리기 때문에 Update문에서는 지양해야합니다.
// Awake나 Start 함수에서 할당한 후 사용해주세요.
playerTrans = GameObject.FindWithTag("Player").GetComponent<Transform>();
// NavMeshAgent 입니다.
agent = GetComponent<NavMeshAgent>();
// 몬스터의 상태를 체크하는 코루틴 함수 입니다.
StartCoroutine(CheckMonsterState());
}
// 일정 시간마다 몬스터의 행동을 체크합니다.
IEnumerator CheckMonsterState()
{
while (!isDie)
{
yield return new WaitForSeconds(0.3f);
// 몬스터와 플레이어의 사이의 거리를 측정합니다.
float distance = Vector3.Distance(playerTrans.position, monsterTrans.position);
// 공격 사정거리 범위로 들어왔는지 확인합니다.
if (distance <= attackDis)
{
state = MonsterState.ATTACK;
}
// 쫓는 사정거리 범위로 들어왔는지 확인합니다.
else if (distance <= traceDis)
{
state = MonsterState.TRACE;
}
// 둘 다가 아니면 IDLE 상태로 대기합니다.
else
{
state = MonsterState.IDLE;
}
}
}
3. 몬스터의 변화에 따라 행동을 취하는 함수입니다.
IDLE 상태에선 쫓기를 멈춥니다.
TRACE 상태에선 플레이어의 좌표로 이동합니다.
ATTACK과 DIE도 작성해주었습니다.
void Start()
{
// 몬스터의 상태에 따라 몬스터의 동작을 제어하는 함수입니다.
StartCoroutine(MonsterAct());
}
IEnumerator MonsterAct()
{
while (!isDie)
{
switch (state)
{
// IDLE 상태입니다.
case MonsterState.IDLE:
// 쫓기를 멈춥니다.
agent.isStopped = true;
break;
// TRACE 상태입니다.
case MonsterState.TRACE:
// 쫓는 대상의 좌표로 이동합니다.
agent.SetDestination(playerTrans.position);
agent.isStopped = false;
break;
// ATTACk 상태입니다.
case MonsterState.ATTACK:
break;
// DIE 상태입니다.
case MonsterState.DIE:
break;
}
yield return new WaitForSeconds(0.3f);
}
}
전체 스크립트
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// 내비게이션 기능을 사용하기 위해 꼭 추가해주세요.
using UnityEngine.AI;
public class MonsterControl : MonoBehaviour
{
// 몬스터들의 다양한 상태들을 Enum으로 만들어 놓습니다.
public enum MonsterState
{
IDLE, TRACE, ATTACK, DIE
}
// 몬스터의 현재상태입니다. (가만히 있기)
public MonsterState state = MonsterState.IDLE;
// 쫓는 사정거리를 지정합니다.
public float traceDis = 8.0f;
// 공격 사정거리를 지정합니다.
public float attackDis = 2.0f;
// 몬스터의 생존여부입니다.
public bool isDie = false;
private Transform monsterTrans;
private Transform playerTrans;
private NavMeshAgent agent;
void Start()
{
// 몬스터의 Transform 입니다.
monsterTrans = GetComponent<Transform>();
// 몬스터가 쫓아야 하는 플레이어의 Transform 입니다.
// FindWithTag와 같은 Find 함수는 처리속도가 느리기 때문에 절대 Update문에서는 지양해야합니다.
//Awake나 Start 함수에서 할당한 후 사용해주세요.
playerTrans = GameObject.FindWithTag("Player").GetComponent<Transform>();
// NavMeshAgent 입니다.
agent = GetComponent<NavMeshAgent>();
// 몬스터의 상태를 체크하는 코루틴 함수 입니다.
StartCoroutine(CheckMonsterState());
// 몬스터의 상태에 따라 몬스터의 동작을 제어하는 함수입니다.
StartCoroutine(MonsterAct());
}
// 일정 시간마다 몬스터의 행동을 체크합니다.
IEnumerator CheckMonsterState()
{
while (!isDie)
{
yield return new WaitForSeconds(0.3f);
// 몬스터와 플레이어의 사이의 거리를 측정합니다.
float distance = Vector3.Distance(playerTrans.position, monsterTrans.position);
// 공격 사정거리 범위로 들어왔는지 확인합니다.
if (distance <= attackDis)
{
state = MonsterState.ATTACK;
}
// 쫓는 사정거리 범위로 들어왔는지 확인합니다.
else if (distance <= traceDis)
{
state = MonsterState.TRACE;
}
// 둘 다가 아니면 IDLE 상태로 대기합니다.
else
{
state = MonsterState.IDLE;
}
}
}
IEnumerator MonsterAct()
{
while (!isDie)
{
switch (state)
{
// IDLE 상태입니다.
case MonsterState.IDLE:
// 쫓기를 멈춥니다.
agent.isStopped = true;
break;
// TRACE 상태입니다.
case MonsterState.TRACE:
// 쫓는 대상의 좌표로 이동합니다.
agent.SetDestination(playerTrans.position);
agent.isStopped = false;
break;
// ATTACk 상태입니다.
case MonsterState.ATTACK:
break;
// DIE 상태입니다.
case MonsterState.DIE:
break;
}
yield return new WaitForSeconds(0.3f);
}
}
}
지금은 큐브로 되어있기 때문에 애니메이션은 추가하지 않았지만 추후에 애니메이션도 추가하겠습니다.
'Unity > SnowFight' 카테고리의 다른 글
[SnowFight] 몬스터 만들기 (NavMeshAgent) (0) | 2022.12.13 |
---|
댓글