내일배움캠프 TIL

내일배움캠프 32일차 TIL "제대로 생성되지 않는 아이템"

Jooglorystar 2024. 10. 29. 21:00

 

 

아이템을 생성하는데, 아이템이 사라졌을 때, 일정시간 간격을 두며 생성하게 하고 싶어서 다음과 같은 코드를 작성했었다.

 

public class ItemRegener : MonoBehaviour 
{ 
    [SerializeField] private GameObject prefab; 
    private GameObject spawnedItem; 
    private float spawnTime = 1f; 
    
    private void Start() 
    { 
        spawnedItem = Instantiate(prefab, transform); 
    } 
    
    private void Update()
    { 
        if (spawnedItem == null) 
        { 
            StartCoroutine(RegenItem()); 
        } 
    } 
    
    private IEnumerator RegenItem() 
    { 
        yield return new WaitForSeconds(spawnTime); 
        spawnedItem = Instantiate(prefab, transform); 
    } 
}

 

원래 의도대로라면 spawnTime인 아이템을 사용해서 사라진 뒤, 1초마다 다시 생성되어야 했다.

그러나 처음 사라졌을 때는 제대로 생성되었지만, 두번째부터는 간격이 제대로 반영되지 않고 나오기 시작했다.

해당코드에서는 제거한 기능이지만, 재생성 횟수를 제한하고자 만든 spawnCount라는 변수와 spawnCount--또한 한번만 작동하는 것이 아닌 거의 매 프레임마다 1씩 감소하는 것을 확인할 수 있었다.

 

원인은 Update에서 코루틴이 지속적으로 시작되기 때문이었다.

그래서 나는 해당 생성이 끝난 뒤에 해당 코루틴을 null로 만들어 종료하고, 코루틴 시작 조건에는 해당 코루틴이 null이 아닐 것을 추가하였다.

 

public class ItemRegener : MonoBehaviour
{
    [SerializeField] private GameObject prefab;
    private GameObject spawnedItem;
    private float spawnTime = 1f;

    private Coroutine coroutine;

    private void Update()
    {
        if (spawnedItem == null && coroutine == null)
        {
            coroutine = StartCoroutine(RegenItem());
        }
    }

    private IEnumerator RegenItem()
    {
        yield return new WaitForSeconds(spawnTime);
        spawnedItem = Instantiate(prefab, transform);
        coroutine = null;
    }
}

 

위 코드로 수정하니, 아이템이 생성된 뒤에 코루틴이 종료되고, 여러번 시도 해도 정상적으로 작동하는 것을 확인할 수 있었다.

이에 다음과 같이 다시 spawnCount를 추가하였다.

 

public class ItemRegener : MonoBehaviour
{
    [SerializeField] private GameObject prefab;
    private GameObject spawnedItem;
    [SerializeField] private int spawnCount;
    private float spawnTime = 5f;

    private Coroutine coroutine;

    private void Update()
    {
        if (spawnedItem == null && coroutine == null)
        {
            coroutine = StartCoroutine(RegenItem());
        }
    }

    private IEnumerator RegenItem()
    {
        if (spawnCount > 0)
        {
            yield return new WaitForSeconds(spawnTime);
            spawnedItem = Instantiate(prefab, transform);
            coroutine = null;
            spawnCount--;
        }
        else if (spawnCount == -1)
        {
            yield return new WaitForSeconds(spawnTime);
            spawnedItem = Instantiate(prefab, transform);
            coroutine = null;
        }
    }
}

 

spawnCount가 1 이상일 때는 생성하며 0이 되면 생성을 멈추지만, 인스펙터 창에서 spawnCount를 -1로 입력하면 무한히 생성하는 식으로 구현했다. 

coroutine을 한 오브젝트에서 반복적으로 실행할 때는 이러한 초기화가 중요하다는 사실을 배울 수 있었다.