Monster의 기본적인 패턴의 변화 구상
IDLE(대기) : 멈추는 상태
Patrol(정찰) : 순찰하며 가볍게 걷는 상태, 감지 되는 거리에 오게되면 Chase상태로 전환
Chase(추적) : 추격하는 상태로 빠르게 걷는 상태, 플레이어를 추격
Attack(공격) : Chase상태에서 공격범위 내에 들어오면 공격을 실행한다.
Evade(회피) : 필수는 아니지만, 몬스터가 쉽게 죽을수없도록 회피 기능도 구현했다.
Death(죽음) : 체력이 0이되면 몬스터는 사망하며 삭제
이정도로 구성해봤다.
using UnityEngine;
public class EnemyController : MonoBehaviour
{
public enum State
{
IDLE,
CHASE,
PATROL,
ATTACK,
EVADE,
DEATH
}
public State currentState;
private void Awake()
{
currentState = State.CHASE; // 시작 상태 Chsse 설정
}
private void Update()
{
switch (currentState)
{
case State.IDLE:
Idle();
break;
case State.PATROL:
Patrol();
break;
case State.CHASE:
Chase();
break;
case State.ATTACK:
Attack();
break;
case State.EVADE:
Evade();
break;
case State.DEATH:
Death();
break;
}
}
private void Idle()
{
// IDLE 상태에서 수행될 로직
Debug.Log(" 현재 상태 : " + currentState);
}
private void Patrol()
{
// Patrol 상태에서 수행될 로직
Debug.Log(" 현재 상태 : " + currentState);
}
private void Chase()
{
// CHASE 상태에서 수행될 로직
Debug.Log(" 현재 상태 : " + currentState);
}
private void Attack()
{
// ATTACK 상태에서 수행될 로직
Debug.Log(" 현재 상태 : " + currentState);
}
private void Evade()
{
// Evade상태에서 수행될 로직
Debug.Log(" 현재 상태 : " + currentState);
}
private void Death()
{
// DEATH 상태에서 수행될 로직
Debug.Log(" 현재 상태 : " + currentState);
}
}
여기까지 기본 상태완료!
이제 Idle, Patrol, Chase, Attack, Evade, Death에 넣고싶은 내용을 넣어주도록하자.
가볍게 움직이는 코드까지 작성해보겠습니다.
[SerializeField] private float patrolRadius = 5f; //순찰반경
[SerializeField] private float partolDuration = 5f; //순찰 후 한 위치에 멈출 시간
[SerializeField] private float detectionRadius = 10f; //적이 플레이어를 감지하는 거리
private Vector3 nextPatrolPoint; //다음 순찰 지점
private Transform playerTransform; //추적할 위치
...
private void Awake()
{
currentState = State.PATROL; //몬스터 생성시 순찰
playerTransform = GameObject.FindGameObjectWithTag("Player").transform; //태그로 찾기
ChooseNextPatrolPoint();
}
먼저 순찰반경, 순찰후 멈출 시간, 플레이어 감지 범위, 순찰지점, 플레이어를 추적할수있게 적었습니다.
그리고 곧장 다음 순찰 지점으로 이동할수있게 만들었습니다.
private void ChooseNextPatrolPoint()
{
//공중으로는 이동 안할거니까 X,Z만
float randomX = UnityEngine.Random.Range(-patrolRadious, patrolRadius);
float randomZ = UnityEngine.Random.Range(-patrolRadious, patrolRadius);
nextPatrolPoint = transform.position + new Vector3(randomX, 0f, randomZ);
}
순찰할 지점 알려주고 움직일수 있도록 아래와 같이 작성
private void Patrol()
{
//패트롤 상태 되었는지 확인
Debug.Log("Current State : " + currentState);
//플레이어의 위치 찾기
float distanceToPlayer = Vector3.Distance(transform.position, playerTransform.positon);
//다음 순찰할 곳 찾기 : 바로 위에서 랜덤하게 생성했죠?
float distanceToPatrolPoint = Vector3.Distance(transform.position, nextPatrolPoint);
//플레이어가 반경내에 들어왔다면 추적상태로 변경
if (distanceToPlayer <= detectionRadius)
{
currentState = State.CHASE;
return;
}
//순찰 지점에 거의 도착했다면
if (distanceToPatrolPoint <= 0.5f) //0.5는 임의의 값
{
currentState = State.IDLE; //대기 상태로 전환
StatCoroutine(StayForAWhile()); //대기하면서 뭐할지 코루틴 작성
return;
}
//위에 해당되는 내용이 없다면 이동한다 (else)
transform.position = Vector3.MoveTowards(transform.position, nextPatrolPoint, speed * Time.deltaTIme);
}
조건 두개를 걸고 좀전에 찾은 순찰지점을 향해 이동합니다. 조건 두개는 다음과 같습니다. 플레이어가 감지되는 거리에 왔으면 추적을위해 추적 상태로 전환하거나.
private IEnumerator StayForAWhile()
{
Debug.Log("순찰 끝! 잠깐 쉬자..");
//잠깐 쉬고, 다음 순찰 지점 찾기
yield return new WaitForSeconds(patrolDuration);
ChooseNextPatrolPoint();
//다시 순찰 상태로 전환
currentState = State.PATROL;
}
순찰지점 다 도착했으면 잠깐 쉬었다 다시 순찰할수있도록 코루틴을 작성.

추적 공격 회피 죽음 등은 나중에...
'Unity Engine > Unity 3D.' 카테고리의 다른 글
| [Unity 3D] Floating Capsule 경사면 해결 (0) | 2023.11.04 |
|---|---|
| [유니티 3D] Enemy 상태패턴 작성 (0) | 2023.10.22 |
| [유니티 3D] 메기도 구현 (무한히 튕기는 광선) (1) | 2023.10.21 |
| 일정한 간격으로 오브젝트 생성 (0) | 2023.10.20 |
| 유니티 3D 잔상효과 (1) | 2023.10.20 |