패링 게임 - 2 (코루틴)

Labin·2025년 4월 7일

패링 게임

목록 보기
4/14

코루틴

코루틴이란?
일시 중지할 수 있는 함수
Unity에서 일을 한 번에 다 하지 않고, 잠깐 멈췄다가 나중에 다시 계속 실행할 수 있는 함수야.

즉, 시간을 기반으로 동작을 나눠 처리하고 싶을 때 사용하는 기능!

📦 일반 함수 vs 코루틴
일반 함수 코루틴
한 번에 다 실행됨 중간에 멈췄다가 다시 실행됨
void MyFunc() IEnumerator MyCoroutine()
시간 지연 불가능 yield return으로 지연 가능

StartCoroutine(MyCoroutine());



IEnumerator MyCoroutine() {
    Debug.Log("Start");

    yield return new WaitForSeconds(2f); // 2초 멈춤

    Debug.Log("After 2 seconds");
}

new WaitForSeconds(x) x초 동안 멈춤
null 다음 프레임까지 대기
new WaitUntil(() => 조건) 조건이 참일 때까지 대기
new WaitForEndOfFrame() 렌더링 끝날 때까지 대기

🎮 언제 쓰냐?
애니메이션 끝날 때까지 기다릴 때

공격 후 후딜 주기

몬스터 스폰 주기 만들기

페이드 인/아웃 같은 시간 기반 연출

상태 전환 타이밍 맞추기

⛔ 주의할 점
StartCoroutine()으로 실행해야 함

리턴값은 못 받음 (코루틴은 값을 반환 안 해)

중간에 StopCoroutine()으로 끊을 수 있음

       //Attack
        if(Input.GetMouseButtonDown(0)) {
            //공격 속도 적용
            StartCoroutine(PlayAttackAnimation());
        }
       
       
           IEnumerator PlayAttackAnimation()
    {
        m_animator.speed = m_stats.attackSpeedMultiplier;
        m_animator.SetTrigger("Attack");


        //애니메이션 기다림
        AnimatorClipInfo[] clipInfos = m_animator.GetCurrentAnimatorClipInfo(0);
        //만약 재생중인 애니메이션이 있다면 그 길이를 가져옴. 없다면 0.5초 반환
        float clipLength = clipInfos.Length > 0 ? clipInfos[0].clip.length : 0.5f; // fallback 0.5초
        yield return new WaitForSeconds(clipLength / m_stats.attackSpeedMultiplier);

        m_animator.speed = 1.0f;
    }

공격속도 증가를 주고 싶은데, 이를 그냥 함수로 적용하면 애니메이션 실행 전에 바로 원래 공격속도로 돌아오므로 공격속도를 애니메이션 끝나고 돌아오게 함수 적용


해결한 문제

1

Hero의 히트 센서와 웨폰 콜라이더가 겹쳐서 항상 자기 자신이 맞던 문제를 레이어를 나눠서 프로젝트 세팅에서 아예 충돌을 막아버림.

2

공격을 맞았을 때 센서로 OnTriggerEnter2D로 체크하고 이를 몬스터에서 처리하는 방법이었는데

Monster


if (m_hitSensor.State())
        {
            Debug.Log("맞음");
            m_animator.SetTrigger("Hurt");
            m_hitSensor.Disable(m_invincibleTimer);
        }
        
Sensor

public class Sensor_Monster : MonoBehaviour {

    private int m_ColCount = 0;

    private float m_DisableTimer;

    private void OnEnable()
    {
        m_ColCount = 0;
    }

    public bool State()
    {
        if (m_DisableTimer > 0)
            return false;
        return m_ColCount > 0;
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        Debug.Log("몬스터 충돌 감지: " + other.name);
        m_ColCount++;
        Debug.Log("enter 충돌 체크: " + m_ColCount);
    }

    void OnTriggerExit2D(Collider2D other)
    {
        m_ColCount--;
        Debug.Log("exit 충돌 체크: " + m_ColCount);
    }

    void Update()
    {
        m_DisableTimer -= Time.deltaTime;
    }

    public void Disable(float duration)
    {
        m_DisableTimer = duration;
    }
}

공격이 너무 빠르면 Update가 실행되기 전에 ColCount값이 0이 되서 결국 맞기도 전에 판정이 끝남. 이를 해결하기 위해 Sensor로 hurt에 관련된 값을 옮김.
항상 Update()가 즉시 실행되는게 아니란 걸 생각하자

3

가드를 작동하는 도중에 다른 애니메이션이 1프레임만 실행됨. 아마도 이것 역시 입력받는 타이밍 문제인 것 같음.

그래서 애니메이션 조건문에 guard가 false일 때로 했음. 근데 다른 공격은 트리거 형식으로 해놨는데 이걸 선입력 받아서 이미 가드상태에서 다음 공격을 받고 가드가 끝나면 무조건 실행함

        //Guard
        bool isGuarding = Input.GetMouseButton(1);
        m_animator.SetBool("Guard", isGuarding);

        if (!m_animator.GetBool("Guard"))
        {
            //Attack
            if(Input.GetMouseButtonDown(0)) {
                //공격 속도 적용
                StartCoroutine(PlayAttackAnimation());
            }

            //Parrying
            else if(Input.GetKeyDown("f"))
                m_animator.SetTrigger("Parrying");
        }

그냥 막아버림

profile
공부를 기록하는 공간

0개의 댓글