Hierarchy에 있는 GameObject를 Project란에 드래그로 올리면 Prefab으로 생성이 된다.
Prefab은 간단히 말하면 클래스 같은 것이고, Hierarchy에 있는 것은 Instance라고 보면 된다.
즉, 틀을 저장한다고 생각하면 된다. 같은 적을 만들 때 Prefab을 이용하면 더 적은 비용으로 효율을 낼 수 있다.
prefab을 수정하면 Hierarchy에 있는 모든 값도 수정된다.
prefab의 수정 방법은 다음과 같다.
1. prefab을 더블 클릭하여 prefab을 수정한다. (inspector 창을 이용할 수 있다.)
2. hierarchy에서 Instance의 이름 우측에 보면 >이 있는데 이 버튼을 눌러도 prefab을 수정할 수 있다.
프리팹을 클래스로 비유했는데 그 이유는 3가지 버전의 prefab이 존재하기 때문이다.
일단 우리가 방금까지 사용한 기본 prefab이다.
그리고 Nested Prefab으로 prefab 2개 이상을 하나의 게임 오브젝트로 만든 것으로 (즉, 2개 이상의 prefab을 자식으로 두는 GameObject) 다시 prefab을 만드는 것이다.
마지막으로 Prefab variant로 Prefab의 Instance를 다시 Project에 옮길 경우 2가지 선택지가 나온다. 원본을 바꿀 것인지, 혹은 원본 Prefab을 상속해서 새로운 Prefab을 만들 것인지다. Prefab variant는 후자를 얘기한다.
Tip. Prefab으로 만들어진 Instance로 만든 것에서 Intance의 특정 값만 변경할 수 있다.
이제 코드 상으로 Prefab을 Hierarchy창에 Instance로 만드려고 한다.
가장 간단한 방법은 다음과 같다.
using UnityEngine;
public class CreateInstance : MonoBehaviour
{
public GameObject go;
void Start()
{
GameObject obj = Instantiate(go);
Destroy(obj, 10);
}
void Update(){ }
}
다음과 같이 스크립트를 짜고서 아래와 같이 Unity 엔진에서 Mapping 시켜주는 것이다.
스크립트에서는 public으로 변수를 선언할 경우 유니티 엔진에서 직접 연결을 할 수 있다.
특이한 점으로 project 뷰에있는 Prefab도 GameObject처리한다는 것이다.
추측으로는 Unity엔진 내부적으로 스크립트든 Prefab이든 내부적으로는 1개씩 모두 생성해두고, Hierarchy에 clone해서 두는게 아닌가 싶다. 어디까지나 추측이니까 믿지는 말자.
Instantitate(GameObject)는 Prefab을 생성해준다.
Destroy(GameObject,float)의 경우 GameObject를 float초 후에 삭제해준다.
기본형으로 Destroy(GameObject)도 존재한다.
여기서 주의할 점은 prefab의 go와 Instantitate(prefab)으로 생성한 GameObject는 다르다는 점이다.
위와같이 public GameObject로 선언하기 싫다면 attribute로 [serializeFiled]를 선언해주면 된다.
[SerializeField]
private GameObject go;
이처럼 Unity Engine을 통해서 Mapping 시켜줄 수도 있지만 이는 유지보수 측면에서 바람직하지 않다. 따라서 코드를 사용해서 Prefab을 불러오는 것이 더 좋다.
코드를 통해서 불러오려면 Resources 클래스를 사용하면 된다.
이 클래스는 자산을 포함한 개체를 찾고 엑세스 할 수 있다. Assets 폴더의 "Resources"라는 폴더에 있는 자산을 Resources.Load 함수를 통해 액세스 하는데 반드시 "Resources"라는 이름이어야 한다.
그 이유는 유니티에서는 일반적으로 경로 이름을 사용하여 엑세스하지 않기 때문이다. 자산을 "Resources"에 배치하면 Resources 폴더의 모든 자산이 빌드에 포함된다.
Resources.Load는 Resources 폴더 path에 저장된 요청 유형의 자산을 로드하는데 찾지 못할 경우 null을 반환한다. 주의할 점은 unity의 모든 자산 이름과 경로는 슬래시를 사용한다. 또 path의 경우 대소문자를 구분하지 않으며 파일 확장자를 포함하지 않아야 한다.
그리고 path는 "Assets/Resources/"를 생략하고 작성한다.
using UnityEngine;
public class CreateInstance : MonoBehaviour
{
void Start()
{
GameObject go = Resources.Load<GameObject>("Prefab/TestObject");
GameObject instant = Instantiate(go);
Destroy(instant, 5);
}
void Update(){ }
}
Resources에 대한 Unity Docs이다.
https://docs.unity3d.com/ScriptReference/Resources.Load.html
https://docs.unity3d.com/ScriptReference/Resources.html