¿Destruir un Prefab en un Array instanciado?.

UnLiMiTeD

A ver si me explico.

Estoy haciendo un generador de datos planetarios. Tenemos por ejemplo 4 datos, tamaño, distancia, oxigeno y orbita. Tambien he creado distintos "planetas" que he metido en un array, para que se instancien junto con los datos. Cuando pulso la tecla Space, se instancia todo esto. En este gif quedara todo mas claro.

Hasta aqui sin problemas. La pega que tengo es que yo quiero poder estar pulsando ciclicamente el Space, destruya todo lo anterior y haga una nueva instancia.

Este es el codigo donde tengo metido el array con los planetas y los datos random que se generan.

Lo tengo en el Start por que luego desde otro objeto Instancio un prefab donde esta el canvas y ese script.

El problema que tengo es que, se destruye el canvas y se vuelve a instanciar, pero los planetas que se instancian de los arrays no desaparecen, esto es lo que sucede en Hierachy cada vez que pulso el Space.

( se ve primero el Game y luego Hierachy ).

¿Se os ocurre cual puede ser el problema o una mejor solucion para hacer lo que busco?.

totespare

Ese GameObject buscador qué es? Te pasa por el else if de la segunda foto? Si te pasa, prueba a añadirle un .gameObject al clone, que a veces a mi me ha pasado cosas raras y si no le especificaba que es la referencia a si mismo, no me iba bien, no se por qué

B

No es buena práctica, se deberían reutilizar en vez de crear y destruir.

Ahora, el problema es que no estás destruyendo los planetas... una solución es instanciar los planetas usando una variable pública en "buscador", y usarla desde "ejecutabuscador" para destruir los planetas antes de destruir el "buscador".

Pon como pública intPlanet en "buscador"... y agrega antes del destroy de "ejecutabuscador" esta línea

Destroy(clone.GetComponent<Buscador>().intPlanet);

Otra posibilidad más sencilla... que también debería servir, es hacer los planetas hijos de buscador.

1 1 respuesta
UnLiMiTeD

#3 Oh, ha funcionado a las mil maravillas!!. Gracias!.

Aunque como dices, si no es buena practica... ¿Que seria lo ideal, tenerlo todo en la jerarquia, desactivado e ir activando y desactivando?.

2 respuestas
profmoriarty

#4 Yo crearía una lista de objetos para que se almacenen ahí al ser "destruidos" y llamarlos a placer, así sería mas óptimo.

B

#4 Se llama pooler. Consiste en un prefab predefinido y vacio del elemento que quieres crear. De una manera lo deshabilitas/habilitas con los datos que desees.

A ver si en casa paso algún tuto.

Yo los uso bastante para objetos de inventario o seleccionables. Logros o cualquier cosa que contenga elementos dinamicos de datos.

Para mostrar valas va tb perfecto ;...;

1 respuesta
Czhincksx

Como dice #6 un pool es la solución.

Te paso el código del mío. Este busca un prefabs en la carpeta Resources\Projectiles y lo instancia.

Sólo tendrías que cambiar la clase de BaseProjectile por GameObject o la clase que quieras que devuelva el pool. Este pool lo puedes poner en la escena y como es un singleton puedes llamar a sus métodos a partir de su instancia estática.

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

namespace td.gameplay.turrets {
	public class ProjectilesPool : MonoBehaviour {

	public static ProjectilesPool _instance;

	public Dictionary<string, Queue<BaseProjectile>> projectiles = new Dictionary<string, Queue<BaseProjectile>>();

	void Awake () {
		if (_instance == null) {
			_instance = this;
		}
	}

	public BaseProjectile LoadProjectile(string _id) {
		if (projectiles.ContainsKey (_id) && projectiles [_id].Count > 0) {
			return projectiles [_id].Dequeue ();
		} else {
			GameObject go = Resources.Load<GameObject> ("Projectiles/" + _id);
			BaseProjectile projectile = Instantiate(go, Vector3.zero, Quaternion.identity).GetComponent<BaseProjectile>();
			projectile.gameObject.name = _id;
			return projectile;
		}
	}

	public void UnloadProjectile(BaseProjectile _projectile) {

		string id = _projectile.gameObject.name;

		if (projectiles.ContainsKey (id)) {
			projectiles [id].Enqueue (_projectile);
		} else {
			Queue<BaseProjectile> pQueue = new Queue<BaseProjectile> ();
			pQueue.Enqueue (_projectile);
			projectiles.Add (id, pQueue);
		}
		_projectile.transform.parent = this.transform;
	}
}
}

Para usarlo:

ProjectilesPool._instance.LoadProjectile("NombreDelPrefab");

ProjectilesPool._instance.UnloadProjectile(ObjetoADevolver);

Si quieres en el Unload puedes hacer que se desactive el objeto, puesto que ya ha vuelto al pool. Todo depende de si quieres que lo desactive el pool o quieres controlarlo tú por algún motivo. Si lo desactivas en el unload acuérdate de activarlo de nuevo tras hacerle Load e inicializarlo como necesites.

Usuarios habituales