TIL - StateMachine에서 ChaseState가 실행되지 않았던 이유

김보근·2025년 2월 21일

Unity

목록 보기
101/113

TIL - StateMachine에서 ChaseState가 실행되지 않았던 이유

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()
    {
        
    }
}
profile
게임개발자꿈나무

0개의 댓글