Creación de mallas (meshes) de forma programática en Unity

Banner Malla Programatica

Como sabemos Unity permite importar modelos 3d de forma muy sencilla, pero ¿y si en alguna ocasión necesitamos crear modelos y usarlos como objetos de juego usando sólamente código? ¿Es esto posible? La respuesta es sí, y en este tutorial veremos cómo hacerlo. Crearemos una malla de 4 vértices, le añadiremos color y un collider, de forma que sea como cualquier otro gameobject de la escena.

Una malla poligonal o mesh no es más que una serie de vértices relacionados entre sí formando triángulos, con una serie de propiedades como coordenadas de textura o vectores normales. La mayoría de elementos y personajes que pueblan las escenas de un videojuego son mallas poligonales formadas por conjuntos de triángulos.

Aunque normalmente los modelos 3d los crearíamos en un editor aparte y los importaríamos a Unity, no significa que no podamos crearlos usando únicamente código. Veamos cómo crear un cuadrado, formado por 2 triángulos.

Crearemos una nueva escena en Unity y un script C# que asignaremos a la cámara o a cualquier objeto de la escena (es indiferente). El código completo del script es el siguiente:


using UnityEngine;
using System.Collections;

public class Test : MonoBehaviour
{

	void Start ()
	{
		CreateSquare(0.0f,0.0f,3.0f,3.0f);
	}

	void CreateSquare(float posX, float posY, float width, float height)
	{
		//GAME OBJECT
		GameObject obj = new GameObject("ScriptedSquare");

		// MESH
		obj.AddComponent("MeshFilter");

		Mesh m = new Mesh();
		m.name = "ScriptedMesh";

		m.vertices = new Vector3[] {
			new Vector3(-width/2, -height/2, 0.0f),
			new Vector3(width/2, -height/2, 0.0f),
			new Vector3(width/2, height/2, 0.0f),
			new Vector3(-width/2, height/2, 0.0f)
		};

		m.uv = new Vector2[] {
			new Vector2 (0, 0),
			new Vector2 (0, 1),
			new Vector2(1, 1),
			new Vector2 (1, 0)
		};

		m.triangles = new int[] { 0, 3, 2, 0, 2, 1};
		m.RecalculateNormals();	

		obj.GetComponent<MeshFilter>().mesh = m;

		//COLLIDER
		obj.AddComponent("BoxCollider2D");
		obj.GetComponent<BoxCollider2D>().size = new Vector2(width,height);

		//MATERIAL
		obj.AddComponent("MeshRenderer");

		Material mat = new Material(Shader.Find("Self-Illumin/Diffuse"));
		mat.SetColor("_Color", new Color(Random.Range(0.0f,1.0f),
		                                 Random.Range(0.0f,1.0f),
		                                 Random.Range(0.0f,1.0f)));
		obj.renderer.material = mat;

		//POSITION
		obj.transform.position = new Vector3(posX,posY,0.0f);
	}
}

El nombre de la clase es irrelevante para este caso (pero que coincida con el nombre del fichero!), siendo lo importante la función CreateSquare. El código es muy sencillo pero vamos a ver las partes más importantes.

La función recibe como parámetros la posición en 2d del cuadrado y su ancho y alto. Lo primero que hace la función es crear un nuevo GameObject, que contendrá la malla que vamos a crear.

Después se crea la propia malla (Mesh), que es donde definiremos los vértices del cuadrado. Es interesante comprender cómo se definen los vértices y los dos triángulos que forman el cuadrado.

Como vemos, en primer lugar se definen los 4 vértices que formarán el cuadrado en m.vertices. Esta definición es simplemente un listado de los vértices, sin determinar ninguna relación entre ellos. En la siguiente imágen podemos ver la correspondencia de estos vértices con el cuadrado que crearemos:
square1
A continuación se asigna a cada vértice su correspondiente coordenada UV, necesaria si quisiéramos aplicarle una textura a la malla.

Es en m.triangles donde determinamos los triángulos que forman los vértices. El orden de los vértices es muy importante pues determina la orientación de la cara (su vector normal), es decir, desde qué lado se puede ver. Para que la cara mire hacia nosotros, el orden de los vértices debe darse en sentido antihorario. En la siguiente imagen puede verse el orden seguido al especificar los triángulos.
square2
Tras esto se recalculan las normales y se asigna la malla al componente MeshFilters del GameObject creado.

A continuación se le añade un BoxCollider2D del mismo tamaño que el cuadrado y un MeshRenderer que determinará el material del mismo. En mi caso he escogido un shader de tipo “Self-Illumin/Diffuse” con un color aleatorio, pero puede usarse el que se quiera.

Y eso es todo! Al ejecutar el proyecto veremos cómo se crea un cuadrado de forma programática en la escena. Este cuadrado es un GameObject normal y corriente por lo que podría interactuar con cualquier otro elemento de la escena.
Captura de pantalla 2014-10-22 16.43.24

Ahora podemos hacer algún experimento variando la llamada a CreateSquare:


for(int i = 0; i < 200; i++)
{
	CreateSquare(Random.Range(-5.0f,5.0f),Random.Range(-5.0f,5.0f),1.0f,1.0f);
}

Captura de pantalla 2014-10-22 17.32.42

😀

Banner Blog

Anuncios

5 pensamientos en “Creación de mallas (meshes) de forma programática en Unity

  1. Muy interesante la verdad, tal vez considerarías hacer tutoriales de UE4 no hay muchos en español seria estupendo igual muy interesante la creación de mallas por código

  2. Pingback: Creación de mallas (meshes) de forma programática en Unity | El … | Chicas

  3. Pingback: Motores Gráficos de VideoJuegos III: Unity 5 – appsandroidsite

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s