[Unity] 게임 오브젝트 생성 시스템 & 코루틴(coroutine)

치치·2025년 8월 29일
0

Unity

목록 보기
27/27
  • prefab 시스템을 사용하여 게임 오브젝트를 prefab화 시켜주기

  • Hierarchy > create Empty > 위치값 리셋 후 이름 바꿔주기 (Create Manager)

  • C# scripts CreateManager 생성

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CreateManager : MonoBehaviour
{
    [SerializeField] GameObject foods;

	void Start()
    {
    	Instantiate(food);
    }
}

[SerializeField] GameObject food;
GameObject라는 클래스의 food라는 객체(인스턴스)를 선언

Instantiate: 오브젝트 생성 함수

  • CreateManager 스크립트를 생성한 CreateManager게임오브젝트로 드래그

  • prefab을 스크립트의 Food부분에 넣어주기

  • 화면상 게임오브젝트가 생성되었다

위에 작성된 코드와 prefab이 게임오브젝트에 동적할당되는 과정을 더 자세히 알아보자 ⭕

만약 씬창에 생성된 현재 게임오브젝트를 수정하려면? ⭕

새로운 인스턴스(객체)를 생성해주어야함!!

  • 이유는 : 현재 food가 참조하고 있는것은 prefab이기 때문에 씬창에 보여지고 있는 복제된 객체를 가리키는 것이 아님!!

  • 새로 인스턴스를 지정하여 이를 수정하면 씬창의 게임오브젝트에 반영된다
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CreateManager : MonoBehaviour
{
    [SerializeField] GameObject food;

    [SerializeField] GameObject clone; // 게임오브젝트 접근하기 위한 참조변수

    private void Start()
    {
        clone = Instantiate(food);

        clone.transform.position = new Vector3(1,1,1); // == Vector3.one;
    }
}

씬창에 게임 오브젝트가 1,1,1 위치에 생성


5초에 하나씩 게임 오브젝트 생성하기 구현🍓

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CreateManager : MonoBehaviour
{
    [SerializeField] GameObject food;

    [SerializeField] GameObject clone; // 게임오브젝트 접근하기 위한 참조변수

    [SerializeField] float time;

    private void Update()
    {
        // time에 deltaTime 누적
        time += Time.deltaTime;

        if(time >= 5.0f)
        {
            clone = Instantiate(food);

            time = 0.0f;
        }
    }
}
  • 5.0f 가 넘어가면 게임 오브젝트 하나 생성 후 time 다시 0.0f 로 돌아가서 반복

  • 현재 코드는 Update()에서 프레임단위로 계속 처리하는거라 비효율적

  • 시간 같은건 Update()함수에 사용하는건 비효율적

Time.deltaTime 이란❓

  • 프레임마다 시간이 얼마나 지났는지 알려주는 값
    • 10FPS
      한 프레임마다 걸리는 시간: 1초
      10 프레임 = 0.1초 (Time.deltaTime = 0.1)
    • 20FPS
      한 프레임마다 걸리는 시간: 1초
      20 프레임 = 0.05초 (Time.deltaTime = 0.05)

      결론적으로 1초 동안 이동하는 총 거리는 항상 일정하다

코루틴 (Coroutine)

코루틴은 단일쓰레드에서 동작되고 Main에서 코루틴이 호출되면 코루틴이 실행되고, 특정 시간이 지나서 끝나면 다시 Main에 제어권을 넘겨준다

[SerializeField] float time = 5.0f;

IEnumerator Create()
{
    Debug.Log("Start Coroutine");

    yield return new WaitForSeconds(time);

    Debug.Log("Idle Coroutine");
}
  • 사용은 IEnumerator + 함수이름()
  • 함수 내부에 yield return + 필수로 들어가야함

yield return 종류

  • yield return null : 다음 프레임에 실행
  • yield return WaitForSeconds(float) : 매개변수로 입력한 특정 시간 이후에 실행 (유니티 시간상)
  • yield return WaitForSecondsRealtime(float) : 매개변수로 입력한 특정 시간 이후에 실행 (실제 시간상)

Coroutine함수 호출

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CreateManager : MonoBehaviour
{
    [SerializeField] GameObject food;

    [SerializeField] GameObject clone; // 게임오브젝트 접근하기 위한 참조변수

    [SerializeField] float time = 5.0f;
    
    private void Start()
 	{
     	StartCoroutine(Create());
 	}
    
 	IEnumerator Create()
 	{
     	Debug.Log("Start Coroutine");

     	yield return new WaitForSeconds(time);

     	Debug.Log("Idle Coroutine");
    }
}
  • coroutine호출하려면 start함수에서 StartCoroutine(함수이름());

  • 스크립트 내에서 time의 값을 5.0f로 지정했어도 유니티 에디터 내에 스크립트에서 또 수정해주어야함

  • 실행 시 Start Coroutine이 실행되고 5초 후에 Idle Coroutine이 실행

Coroutine을 반복해서 5초마다 생성

[SerializeField] float time = 5.0f;

private void Start()
 	{
     	StartCoroutine(Create());
 	}

IEnumerator Create()
{
    while(true)
    {
        Debug.Log("Start Coroutine");

        yield return new WaitForSeconds(time);

    }
}
  • 5초마다 Coroutine이 실행된다

while문 사용해서 coroutine 실행 문제점❗❗

while문이 실행되는동안 계속해서 new WairForSeconds로 Managed Heap에 동적으로 클래스 객체가 생성된다

C# 가비지컬렉터가 자동으로 메모리를 관리해주긴 하지만, 메모리 효율을 위해 불필요한 동적할당은 금지

캐싱 (Caching) 기법 사용하기

자주 사용하는 데이터나 객체를 미리 생성해두고, 필요할 때마다 새로 생성하지 않고 재사용하여 성능을 최적화하는 기법

waitForSecond 객체를 미리 생성해두고 재사용 하게 되면 yield return 할때마다 새로운 메모리 할당이 발생하지 않음❗

캐싱 사용한 코루틴 코드

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CreateManager : MonoBehaviour
{
    [SerializeField] GameObject food;

    [SerializeField] GameObject clone; // 게임오브젝트 접근하기 위한 참조변수

    WaitForSeconds waitForSecond = new WaitForSeconds(5.0f); // 객체 미리 선언
    
    private void Start()
    {
        StartCoroutine(Create());
    }
    IEnumerator Create()
    {
        while(true) // 코루틴 반복
        {
            Debug.Log("Start Coroutine");

            yield return waitForSecond; // 동적할당 여러번 할 필요x

        }
    }
}



코루틴 중지

1. 코루틴 변수 저장 후 중지

Coroutine co;

co = StartCoroutine(Play());
StopCoroutine(co);

2. 코루틴 내부에 조건을 만족하면 yield break;

int temp = 1;
void Start()
{	
	StartCoroutine(Play());
}

Play()
{
	temp++;
    yield return new WaitForSeconds(1.0f);
	if(temp == 10)
    {
    	yield break;
    }
}

3. IEnumerator 미리 생성 후 지정

private IEnumerator co;

co = Play();
StopCoroutine(co);

// 매개변수가 길때 편리하게 사용할 수 있다.
profile
뉴비 개발자

0개의 댓글