Enemy가 ChaseState로 정상적으로 넘어가는 것 같았는데, 실제로는 처음 플레이어 위치로만 이동하고 멈춰 있었다.
ChaseState.Enter()에서 한 번만 agent.SetDestination(target.position);을 실행하고 끝이었음.
NavMeshAgent는 한 번 목표 위치를 설정하면 계속 갱신되지 않기 때문에, 플레이어가 움직여도 따라가지 못하고 멈춰 있었다.
Enemy의 Update()에서 stateMachine.Update(target.position);을 호출해 ChaseState.Execute()가 지속적으로 실행되도록 수정.
이렇게 하면 agent.SetDestination(target.position);이 계속 갱신되어, 플레이어를 따라가는 것이 정상적으로 작동함.
Enemy스크립트
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class Enemy : MonoBehaviour
{
public int maxHealth;
public int curHealth;
public Transform target;
private StateMachine stateMachine;
private Rigidbody rb;
private BoxCollider bc;
private Material mat;
private NavMeshAgent agent;
private Animator childAnimator;
private void Awake()
{
rb = GetComponent<Rigidbody>();
bc = GetComponent<BoxCollider>();
mat = GetComponentInChildren<MeshRenderer>().material;
agent = GetComponent<NavMeshAgent>();
childAnimator = GetComponentInChildren<Animator>();
stateMachine = new StateMachine();
}
private void Start()
{
stateMachine.SetState(new ChaseState(stateMachine, childAnimator, agent, target));
}
private void Update()
{
stateMachine.Update(target.position);
}
private void FixedUpdate()
{
FreezeRotation();
}
private void FreezeRotation()
{
rb.velocity = Vector3.zero;
rb.angularVelocity = Vector3.zero;
}
private void OnTriggerEnter(Collider other)
{
if(other.tag == "Melee")
{
Weapon weapon = other.GetComponent<Weapon>();
curHealth -= weapon.damage;
Vector3 reactVec = transform.position - other.transform.position;
StartCoroutine(OnDamage(reactVec, false));
}
else if(other.tag == "Bullet")
{
Bullet bullet = other.GetComponent<Bullet>();
curHealth -= bullet.damage;
Vector3 reactVec = transform.position - other.transform.position;
other.gameObject.SetActive(false);
StartCoroutine(OnDamage(reactVec, false));
}
}
public void HitByGrenade(Vector3 explosionPos)
{
curHealth -= 100;
Vector3 reactVec = transform.position - explosionPos;
StartCoroutine (OnDamage(reactVec, true));
}
IEnumerator OnDamage(Vector3 reactVec, bool isGrenade)
{
mat.color = Color.red;
yield return new WaitForSeconds(0.1f);
if(curHealth > 0)
{
mat.color = Color.white;
}
else
{
mat.color = Color.gray;
gameObject.layer = 11;
if (isGrenade)
{
reactVec = reactVec.normalized;
reactVec += Vector3.up * 3;
rb.freezeRotation = false;
rb.AddForce(reactVec * 5, ForceMode.Impulse);
rb.AddTorque(reactVec * 15, ForceMode.Impulse);
}
else
{
reactVec = reactVec.normalized;
reactVec += Vector3.up;
rb.AddForce(reactVec * 5, ForceMode.Impulse);
}
Destroy(gameObject, 4);
}
}
}
Chase상태패턴
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class ChaseState : Istate
{
private StateMachine stateMachine;
private Animator animator;
private NavMeshAgent agent;
private Transform target;
public ChaseState(StateMachine machine, Animator animator, NavMeshAgent agent, Transform target)
{
stateMachine = machine;
this.animator = animator;
this.agent = agent;
this.target = target;
}
public void Enter()
{
animator.Play("Walk");
}
public void Execute(Vector3 playerVector)
{
agent.SetDestination(target.position);
}
public void Exit()
{
}
}