Creación de Misiones de Recolección en Videojuegos
Resumen
Pasar de llegar a una zona a recoger un objeto cambia la lógica del sistema de misiones. Aquí se construye un flujo claro: preparar el objeto con collider, activar la quest al cruzar un start point, detectar la recolección con OnTriggerEnter2D y completar la misión cuando el item coincide. Todo con scripts en C# y referencias simples.
¿Qué cambia en la misión basada en objeto?
La meta ya no es un trigger de zona, sino encontrar y recoger un item. Se coloca una campana en el cementerio y se ajusta su visibilidad con sorting layer en «player» para que quede encima del escenario. Se añade un CircleCollider2D y se marca como isTrigger para poder recogerla con el jugador.
Objetivo: recoger la «Campana del despertar»..
Inicio: clonar el objeto «quest cero start» a «quest uno start». Indicar que inicia la quest 1 cerca de Ricarda..
Textos: inicio «Recoge la campana del despertar». fin «Has conseguido la campana. Que empiece el fin del mundo»..
¿Cómo preparar el objeto con collider y sorting layer?
Poner la campana en el cementerio.
Asignar sorting layer «player» para que se dibuje encima..
Añadir CircleCollider2D y activar «is trigger» para detectar al jugador..
Guardar el objeto y nombrarlo «Campana»..
¿Cómo configurar el inicio y fin de la quest 1?
Clonar «quest cero start» a «quest uno start» y marcar como start point de la quest 1..
Desactivar en jerarquía la quest 1 hasta que el jugador pase por su zona de inicio..
Ajustar los textos de inicio y fin según el objetivo de la campana..
¿Cómo crear el script quest item para recolectar?
Se añade un script de C# llamado «quest item» al objeto campana. Este notifica al manager cuando el jugador lo recoge y desactiva el objeto.
usingUnityEngine;[RequireComponent(typeof(CircleCollider2D))]publicclassQuestItem:MonoBehaviour{publicint questID;// ID de la quest.publicstring itemName;// Identificador del ítem.privateQuestManager manager;// Referencia al manager.voidStart(){ manager =FindObjectOfType<QuestManager>();}voidOnTriggerEnter2D(Collider2D collision){if(collision.gameObject.tag.Equals("Player")){// Solo si la quest está activa y no completada.if(manager.quests[questID].gameObject.activeInHierarchy &&!manager.questsCompleted[questID]){ manager.itemCollected = itemName;// Notificar recolección. gameObject.SetActive(false);// Desactivar la campana (no destruir).}}}}
¿Qué necesita el quest manager para recibir el ítem?
Añadir en el manager una variable pública: public string itemCollected;.
Esta cadena actúa como identificador del último item recolectado..
¿Cómo adaptar el script de la quest para validar el ítem?
Cada quest puede declarar si necesita un objeto y cuál. Luego, en Update, se compara el recolectado en el manager con el requerido. Si coincide, se completa la misión.
publicclassQuest:MonoBehaviour{publicbool needsItem;// ¿La quest requiere ítem?publicstring itemNeeded;// Nombre exacto del ítem requerido.privateQuestManager manager;voidStart(){ manager =FindObjectOfType<QuestManager>();}voidUpdate(){if(needsItem && manager.itemCollected == itemNeeded){ manager.itemCollected =null;// Marcar como usado.CompleteQuest();// Completar misión.}}voidCompleteQuest(){// Lógica de completar: textos de fin, flags, etc.}}
Usa coincidencia exacta entre itemNeeded y itemName. Se pueden usar palabras, números o hashmaps para identificar, según se prefiera..
Ventaja: se añade funcionalidad sin romper lo anterior. Solo se suman campos y una verificación en Update..
¿Qué pruebas y errores comunes se corrigen?
Desactivar la quest 1 en la jerarquía hasta entrar en su zona de inicio..
En la campana: questID = 1 y itemName = "Campana de despertar" (el identificador debe ser idéntico al que espera la quest)..
Activar «is trigger» en el CircleCollider2D para permitir la recolección..
Flujo de validación: iniciar con Ricarda, completar su primera misión en la casa, activar «Recoge la campana del despertar», ir al cementerio, recoger la campana y ver el texto de fin..
¿Te gustaría compartir cómo nombrarías tus ítems o qué otros objetos añadirías al sistema?
Sería interesante tener todos los enemigos dentro de un objeto vacío y mantener este objeto desactivado. Cuando recojamos la campana, activamos el objeto, haciendo que aparezcan todos los enemigos en nuestro mundo
Easy!!!
Encontre que si cambias de escenario las misiones que son de ir de un lugar a otro son fijas a la pantalla. Para solucionar esto sume una validacion de escenario :)
Vamos a tope...
Solo agrégalas al DontDestroyOnLoad y listo.
Agregas el StartTrigger en una escena y el End en la otra.
Hay que agregar unas validaciones más, ya que al cambiar de escena el trigger se activa igual porque los objetos del canvas están dentro del DontDestroyOnLoad.
Para ello en el quest Trigger declaramos unas nuevas variables publicas que contendrán los nombres de las escenas donde se inicia y se termina la misión (tiene que se exactamente igual al nombre de la escena)
public string startPointSceneName, endPointSceneName;
Luego en el OnTriggerEnter2D agregamos la validación del nombre de la escena
privatevoidOnTriggerEnter2D(Collider2D collision){if(collision.CompareTag("Player")){if(!_questManager.questCompleted[questID])//Por si ya fue completada{if(startPoint &&!_questManager.quests[questID].gameObject.activeInHierarchy&&SceneManager.GetActiveScene().name== startPointSceneName)//Si estoy en el punto de inicio y la mision no fue activada anteriormente{ _questManager.quests[questID].gameObject.SetActive(true); _questManager.quests[questID].StartQuest();}if(endPoint && _questManager.quests[questID].gameObject.activeInHierarchy&&SceneManager.GetActiveScene().name== endPointSceneName){ _questManager.quests[questID].CompleteQuest();}}}}