Unity3D/Prefab Array

Unity 3D Prefab Array

Soul-Learner 2014. 3. 10. 12:15

유니티 3D 게임 프로그래밍에서 Prefab 배열을 설정하고 사용하는 예


앞서 사용했던 프로젝트를 그대로 다시 사용하고 Prefab 을 배열에 저장하고 있다가 실행시에 동적으로 생성하는 방법을 적용하려고 한다

각각 모양과 크기가 다른 Cube 3개를 생성하고 Prefab으로 설정하고 스크립트에서 프리팹 배열을 선언한 다음 Inspector 뷰에서 3개의 프리팹을 프리팹 배열에 할당하는 절차를 수행한다


우선 스크립트를 아래처럼 배열을 사용하도록 변경한다

#pragma strict

var prefab:GameObject[];


function Start () {

}


function Update () {

}


function OnTriggerEnter(){

 Instantiate(prefab[0]);

}


유니티에서 사용할 수 있는 배열의 형태는 2가지가 있다. 기존 자바스크립트 방식과 유니티에서 새롭게 지원하는 방식이 있는데, 자바스크립트 방식은 자료형을 지원하지 않으므로 여기서는 적합하지 않다.


위와 같이 스크립트에서 배열을 선언하고 아래의 그림처럼 Inspector 뷰에서 배열원소를 할당할 수 있다.

Inspector 뷰에서 배열이 보이면 Size 항목을 선택하고 배열의 원소 수를 입력한 다음 엔터키를 치면 원소를 할당할 수 있도록 입력란이 생성된다.




2개의 큐를 더 생성하고 Prefab 으로 설정한 다음 드래그하여 Element 0, 1, 2 입력란으로 드래그하여 할당한다




아래처럼 Random.Range() 함수를 사용하면 배열의 원소 중에서 임의의 원소 한개를 선택하여 인스턴스를 생성할 수 있으므로 좀더 다양한 모양의 큐브들이 나타나는 것을 볼 수 있다

#pragma strict

var prefab:GameObject[];


function Start () {

}


function Update () {

}


function OnTriggerEnter(){

 var n:int = Random.Range(0,prefab.Length);

 Instantiate(prefab[n]);

}



FPC 가 지형 가운데 설정한 빈 게임오브젝트의 Collider 영역으로 들어갈 때 OnTriggerEnter() 함수가 실행되므로 이 때 큐브 프리팹이 동적으로 생성되고 생성 즉시 중력의 효과로 인하여 떨어지게 된다. 

위에서 떨어지는 큐브들이 지형의 가운데에 설정한 빈 게임오브젝트의 Collider 영역 밖에서 안으로 들어 올 때도 OnTriggerEnter() 함수가 실행되므로 갑자기 엄청난 수의 프리팹 인스턴스가 생성되는 경우도 있다. Collider 안쪽에서 프리팹 인스턴스가 생성되는 경우에도 OnTriggerEnter() 함수가 호출되므로 연쇄적인 OnTriggerEnter() 함수 호출로 이어진다


이때 프리팹의 인스턴스가 생성되는 위치를 변경하고자 한다면 Project 뷰에 있는 Prefab을 Scene 뷰로 드래그하여 새로이 위치를 설정하고 Inspector 뷰에서 Prefab Apply 버튼을 눌러주면 프리팹의 인스턴스 생성 위치가 변경된다


프리팹이 다수개 생성되어 있을 때 주의할 점은 각각의 큐브들이 Rigidbody, Collider 콤포넌트를 가진 경우에는 물리엔진은 이들 프리팹에 대해서 계속 물리적인 계산을 수행하게 되므로 시스템 리소스를 소모하게 된다는 점이다. 그러므로 더이상 물리적인 반응을 할 필요가 없다면 rigidbody.inKinematic = true 를 설정하여 성능을 고려하여야 한다.


아래의 코드는 생성 후 5초가 지난 프리팹은 더 이상 물리엔진이 적용되지 않도록 설정하여 시스템 리소스를 절약하는 예이다.

#pragma strict

var prefab:GameObject[];


function Start () {

}


function Update () {

}


function OnTriggerEnter(){

 var n:int = Random.Range(0,prefab.length);

 var instance :GameObject = Instantiate(prefab[n]);

 yield new WaitForSeconds(5);

 instance.rigidbody.isKinematic = true;

}