Priv's Blog

StopCoroutine, StartCoroutine 작동을 안할 때 본문

Dev. Study Note/Unity

StopCoroutine, StartCoroutine 작동을 안할 때

Priv 2022. 11. 9. 23:05


 

 

1. IEnumerator 메서드는 실행할 때마다 참조값이 바뀐다.

public void StartWeaponAction(int type = 0) {
        if (type == 0) {    // 좌측 마우스 버튼 클릭; 사격
            if (this.weaponSetting.isAuto == true) {
                StartCoroutine(OnAttackLoop());
            }
            else {
                OnAttack();
            }
        }
    }

    public void StopWeaponAction(int type = 0) {
        if (type == 0) {
            StopCoroutine(OnAttackLoop());
        }
    }

    private void OnAttack() {
        if (Time.time - this.lastAttackTime > this.weaponSetting.attackRate) {
            if (this.playerAnimatorController.MoveSpeed > 0.6f) {   // 달리고 있을 때는 공격 불가
                return;
            }

            this.lastAttackTime = Time.time;    // 발사 시간 업데이트
            this.playerAnimatorController.Play("Fire", -1, 0);
        }
    }

    private IEnumerator OnAttackLoop() {
        while (true) {
            OnAttack();
            yield return null;
        }
    }

위 코드는 동작하지 않는 코드다.

정확히는 StartCoroutine( ) 부분은 잘 동작하겠지만, StopCoroutine( ) 부분이 동작하지 않는다.

StartCoroutine( ) 부분을 보면 OnAttackLoop( ) 메서드를 실행하고 그 반환값을 StartCoroutine( )에게 전달하고 있다.

이는 즉, 메서드를 실행할 때마다 참조값이 바뀐다는 것이다.
(StartCoroutine( )에서 입력한 OnAttackLoop( )와 StopCoroutine( )의 OnAttackLoop( )은 별개라는 것)

이 때문에 StopCoroutine( )과 StartCoroutine( )은 서로 다른 값을 참조하고 있어 예상한 대로 코드가 동작하지 않는다.

이 문제를 해결하려면 아래와 같이 작성한다.

public void StartWeaponAction(int type = 0) {
        if (type == 0) {    // 좌측 마우스 버튼 클릭; 사격
            if (this.weaponSetting.isAuto == true) {
                StartCoroutine("OnAttackLoop");
            }
            else {
                OnAttack();
            }
        }
    }

    public void StopWeaponAction(int type = 0) {
        if (type == 0) {
            StopCoroutine("OnAttackLoop");
        }
    }

    private void OnAttack() {
        if (Time.time - this.lastAttackTime > this.weaponSetting.attackRate) {
            if (this.playerAnimatorController.MoveSpeed > 0.6f) {   // 달리고 있을 때는 공격 불가
                return;
            }

            this.lastAttackTime = Time.time;    // 발사 시간 업데이트
            this.playerAnimatorController.Play("Fire", -1, 0);
        }
    }

    private IEnumerator OnAttackLoop() {
        while (true) {
            OnAttack();
            yield return null;
        }
    }

물론, IEnumerator 타입의 변수를 하나 생성하여 OnAttackLoop를 할당해주고, 이를 StartCoroutine, StopCoroutine 메서드의 매개변수로 넣어줘도 된다.

string 타입으로 매개변수를 넣어주면 오타가 발생했을 때 에러를 잡기 힘들어서 위와 같은 코드는 별로 권장되지 않는다.

 


 


수고하셨습니다!


Comments