[Unity] 유니티 컨텍스트 메뉴를 이용한 오브젝트 배치

Filed under tutorials, unity | Comments Off

(Randomly Placing Objects With Unity ContextMenu)

random_00

유니티 에디터에서 지정된 영역 안에 동일한 게임오브젝트를 크기와 재질을 달리해서 수십 개씩 배치해야 하는 상황이 있을 수 있다. 스크립트에서 Instantiate와 Random 함수를 이용하면 일일이 손으로 처리하는 수고를 덜 수 있다. 그러나 Random 함수를 사용하면 게임을 실핼할 때마다 결과를 예상할 수 없고, 개별적인 수정이 어렵다는 문제가 남는다.  이때 컨텍스트 메뉴(http://docs.unity3d.com/Documentation/ScriptReference/ContextMenu.html)를 이용하면 스크립트의 편리함과 손으로 처리할 때의 예측 가능성을 함께 얻을 수 있다.

씬에 다음과 같이 빈 게임오브젝트를 생성하고, Scale로 원하는 영역을 정의한다. 그 다음 이 게임오브젝트에 다음 스크립트를 추가한다. 여기서는 빨강, 파랑, 노랑, 세 개의 재질을 무작위로 사용하며, 인스턴스의 크기가 X, Y, Z 축에서 각각 달라야 하는 상황을 전제로 한다.

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

public class RandomPlacer : MonoBehaviour {

	public GameObject prefab;

	private float rangeX;
	private float rangeZ;
	private Vector3 randomPos;

	private float randomX;
	private float randomZ;
	private float groundLevel;

	public int instanceNum;
	private Vector3 randomScale;
	public float scaleMin;
	public float scaleMax;

	public Material[] mats;

	private List<Transform> prefabInstances = new List<Transform>();

	// Use this for initialization
	void Start () {

	}

	void OnDrawGizmos() {
		Gizmos.color = Color.green;
		Gizmos.DrawWireCube(transform.position, transform.localScale);
	}

	[ContextMenu("Place")]
	public void Place (){

		rangeX = transform.localScale.x * 0.5f;
		rangeZ = transform.localScale.z * 0.5f;

		for(int i = 0; i < instanceNum; i++){

			randomX = Random.Range(rangeX*-1f, rangeX);
			randomZ = Random.Range(rangeZ*-1f, rangeZ);

			GameObject prefabInstance = Instantiate(prefab, Vector3.zero, Quaternion.identity)as GameObject;

			randomScale = new Vector3(Random.Range(scaleMin, scaleMax),
			                          Random.Range(scaleMin, scaleMax),
			                          Random.Range(scaleMin, scaleMax));

			prefabInstance.transform.localScale = randomScale;

			groundLevel = prefabInstance.transform.localScale.y * 0.5f;
			randomPos = new Vector3(randomX + transform.position.x, groundLevel, randomZ + transform.position.z );
			prefabInstance.transform.localPosition = randomPos;

			prefabInstance.transform.parent = this.transform;

			float randomMat = Random.value;

			if (randomMat <0.33f){

				prefabInstance.renderer.material  = mats[0];

			} else if (randomMat > 0.33f && randomMat < 0.66f) {

				prefabInstance.renderer.material  = mats[1];

			} else {

				prefabInstance.renderer.material  = mats[2];
			}

		}

	}

	[ContextMenu("Remove")]
	public void Remove(){

		foreach(Transform instance in this.transform){

			prefabInstances.Add(instance);

		}

		foreach(Transform prefabInstance in prefabInstances){
			if(prefabInstance != null)
			DestroyImmediate(prefabInstance.gameObject);
		}

		prefabInstances.Clear();

	}

}

다음 코드가 컨텍스트 메뉴를 등록하는 행이다.

[ContextMenu("Place")]

컴포넌트의 컨텍스트 메뉴에 Place 메뉴가 등록된다. 이 메뉴를 선택하면 게임을 실행하지 않도고 Place() 함수의 실행 결과를 에디터에 반영할 수 있다.

오브젝트가 생성된 다음에 하나하나 직접 위치나 크기를 수정할 수 있고, Remove()를 선택하면 배치된 인스턴스를 모두 삭제할 수도 있다.

random_02

Comments are closed.