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 위치에 생성
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초 동안 이동하는 총 거리는 항상 일정하다
코루틴은 단일쓰레드에서 동작되고 Main에서 코루틴이 호출되면 코루틴이 실행되고, 특정 시간이 지나서 끝나면 다시 Main에 제어권을 넘겨준다

[SerializeField] float time = 5.0f;
IEnumerator Create()
{
Debug.Log("Start Coroutine");
yield return new WaitForSeconds(time);
Debug.Log("Idle Coroutine");
}
yield return 종류
- yield return null : 다음 프레임에 실행
- yield return WaitForSeconds(float) : 매개변수로 입력한 특정 시간 이후에 실행 (유니티 시간상)
- yield return WaitForSecondsRealtime(float) : 매개변수로 입력한 특정 시간 이후에 실행 (실제 시간상)
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이 실행

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

while문이 실행되는동안 계속해서 new WairForSeconds로 Managed Heap에 동적으로 클래스 객체가 생성된다
C# 가비지컬렉터가 자동으로 메모리를 관리해주긴 하지만, 메모리 효율을 위해 불필요한 동적할당은 금지
자주 사용하는 데이터나 객체를 미리 생성해두고, 필요할 때마다 새로 생성하지 않고 재사용하여 성능을 최적화하는 기법

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
}
}
}
Coroutine co;
co = StartCoroutine(Play());
StopCoroutine(co);
int temp = 1;
void Start()
{
StartCoroutine(Play());
}
Play()
{
temp++;
yield return new WaitForSeconds(1.0f);
if(temp == 10)
{
yield break;
}
}
private IEnumerator co;
co = Play();
StopCoroutine(co);
// 매개변수가 길때 편리하게 사용할 수 있다.