cube와 capsule로 지형을 만들어주고
네비게이션을 테스트해본다.
Agent와 Navigation 기능을 이용할 AgentManager를 만들어준다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class AgentTest : MonoBehaviour
{
NavMeshAgent agent;
public Transform target;
// Start is called before the first frame update
void Start()
{
agent = GetComponent<NavMeshAgent>();
}
// Update is called once per frame
void Update()
{
agent.destination = target.position;
}
}
정상적으로 동작하는것을 확인하고 기존에 만들던 Scene으로 돌아와서
벽과 바닥에는 Navigation Static, Enemy에는 Agent를 적용한다.
private void UpdateMove()
{
// 현재 위치가 최대 추적 가능 거리를 넘어갔는지 여부를 판단한다.
float trace = Vector3.Distance(originPosition, transform.position);
// 만일, 최대 추적 가능 거리를 넘어갔다면 상태를 복귀 상태로 전환한다.
if (trace > traceDistance)
{
state = State.Return;
}
// target방향으로 이동하다가
//Vector3 dir = target.transform.position - transform.position;
//dir.Normalize();
//transform.position += dir * speed * Time.deltaTime;
agent.destination = target.transform.position;
// 나와 target의 거리를 구해서
float distance = Vector3.Distance(transform.position, target.transform.position);
// 만약 그 거리가 공격거리보다 작으면
if (distance < attackDistance)
{
// Attack으로 전이하고싶다.
state = State.Attack;
agent.isStopped = true;
}
}
private void UpdateAttack()
{
// 시간이 흐르다가
currentTime += Time.deltaTime;
// 만약 현재시간이 공격시간이 되면
if (currentTime > attackTime)
{
// 현재시간을 초기화하고
currentTime = 0;
// 만약 target이 공격거리 밖에 있으면 Move상태로 전이하고싶다.
// 나와 target의 거리를 구해서
float distance = Vector3.Distance(transform.position, target.transform.position);
// 만약 그 거리가 공격거리보다 크다면
if (distance > attackDistance)
{
// Move상태로 전이하고싶다.
state = State.Move;
agent.isStopped = false;
}
// 공격 성공
else
{
// 플레이어를 공격하고
php.AddDamage();
}
}
}
public void AddDamage (int damage)
{
agent.isStopped = true;
Destroy(gameObject);
}
Enemy 전문
더보기
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
// FSM으로 상태를 제어하고싶다.
// 정지, 이동, 공격, 죽음
public class Enemy : MonoBehaviour
{
NavMeshAgent agent;
public float speed = 1;
public float findDistance = 5;
public float attackDistance = 1.5f;
public float traceDistance = 15;
enum State
{
Idle,
Move,
Attack,
Die,
Return
}
State state;
PlayerHP php;
GameObject target;
float currentTime;
float attackTime = 1;
Vector3 originPosition;
// Start is called before the first frame update
void Start()
{
agent = GetComponent<NavMeshAgent>();
state = State.Idle;
target = GameObject.Find("Player");
php = target.GetComponent<PlayerHP>();
// 최초 위치를 originPosition 변수에 저장한다.
originPosition = transform.position;
}
// Update is called once per frame
void Update()
{
if (state == State.Idle)
{
UpdateIdle();
}
else if (state == State.Move)
{
UpdateMove();
}
else if (state == State.Attack)
{
UpdateAttack();
}
else if (state == State.Return)
{
UpdateReturn();
}
}
private void UpdateIdle()
{
// 나와 target의 거리를 구해서
float distance = Vector3.Distance(transform.position, target.transform.position);
// 만약 그 거리가 감지거리보다 작으면
if (distance < findDistance)
{
// Move상태로 전이하고싶다.
state = State.Move;
agent.destination = target.transform.position;
}
}
private void UpdateMove()
{
// 현재 위치가 최대 추적 가능 거리를 넘어갔는지 여부를 판단한다.
float trace = Vector3.Distance(originPosition, transform.position);
// 만일, 최대 추적 가능 거리를 넘어갔다면 상태를 복귀 상태로 전환한다.
if (trace > traceDistance)
{
state = State.Return;
}
// target방향으로 이동하다가
//Vector3 dir = target.transform.position - transform.position;
//dir.Normalize();
//transform.position += dir * speed * Time.deltaTime;
agent.destination = target.transform.position;
// 나와 target의 거리를 구해서
float distance = Vector3.Distance(transform.position, target.transform.position);
// 만약 그 거리가 공격거리보다 작으면
if (distance < attackDistance)
{
// Attack으로 전이하고싶다.
state = State.Attack;
agent.isStopped = true;
}
}
private void UpdateAttack()
{
// 시간이 흐르다가
currentTime += Time.deltaTime;
// 만약 현재시간이 공격시간이 되면
if (currentTime > attackTime)
{
// 현재시간을 초기화하고
currentTime = 0;
// 만약 target이 공격거리 밖에 있으면 Move상태로 전이하고싶다.
// 나와 target의 거리를 구해서
float distance = Vector3.Distance(transform.position, target.transform.position);
// 만약 그 거리가 공격거리보다 크다면
if (distance > attackDistance)
{
// Move상태로 전이하고싶다.
state = State.Move;
agent.isStopped = false;
}
// 공격 성공
else
{
// 플레이어를 공격하고
php.AddDamage();
}
}
}
public void AddDamage (int damage)
{
agent.isStopped = true;
Destroy(gameObject);
}
private void OnDestroy()
{
EnemyManager.instance.COUNT--;
}
void UpdateReturn()
{
// 만일, 나의 현재 위치가 originPosition 위치에서 10센티미터 이상이라면
Vector3 dir = originPosition - transform.position;
if (dir.magnitude > 0.1f)
{
// originPosition 방향으로 이동한다.
transform.position += dir.normalized * speed * Time.deltaTime;
}
// 그렇지 않다면, 나의 위치를 originPosition으로 설정한다.
else
{
transform.position = originPosition;
// 상태를 다시 대기 상태로 전환한다.
state = State.Idle;
}
// 나와 target의 거리를 구해서
//float distance = Vector3.Distance(transform.position, target.transform.position);
// 복귀 중 감지거리 안으로 Player가 들어오면
//if (distance < findDistance)
{
// 상태를 Move 상태로 전이한다.
//state = State.Move;
}
}
}
'공부 > Unity 기초' 카테고리의 다른 글
3D FPS - 11 / 적 시야각 (0) | 2022.05.23 |
---|---|
3D FPS - 10 / 적 생성 유지 (0) | 2022.05.21 |
3D FPS - 8 / 게임 오버 처리 (0) | 2022.05.19 |
3D FPS - 7 / 피격 처리 (0) | 2022.05.19 |
3D FPS - 6 / 위치 복귀 (0) | 2022.05.19 |