overbaal 5 Report post Posted May 30, 2020 Buenas gente, queria preguntar una duda aver si alguien puede darme una idea de como hacer que 2 NPCS dialoguen entre si. He pensado en las Coroutines, que un NPC empieze y luego esa misma llame a otra Coroutine del otro NPc para dialogar pero no se por donde empezar. Gracias de antemano y un saludo! Share this post Link to post Share on other sites
leocub58 208 Report post Posted May 30, 2020 Depende de como lo quieras hacer, si es un diálogo predefinido o si interviene el jugador. Para lo primero, tu solución es funcional, tan solo guarda los textos en un xml o un json y leelos con un ID. La segunda opción es un poco más compleja, pero se puede resumir programando un sistema de nodos (ojo, esto también te puede funcionar para la primera solución). Mi consejo para el sistema de nodos es que utilices xNode. ¡Un saludo! 1 Share this post Link to post Share on other sites
nomoregames 35 Report post Posted May 30, 2020 Te digo lo que haría yo. Siguiendo tu formula y para no complicarme mucho la vida, en vez de hacer que una corrutina se comunique con la otra, crearía un solo script, con una sola corrutina, en la que cada cierto tiempo (el cual seria equivalente a la cantidad de letras que tenga su dialogo), se muestre el texto de uno y luego el de el otro... si quieres te lo pongo en código para aclarar Share this post Link to post Share on other sites
overbaal 5 Report post Posted May 30, 2020 4 hours ago, nomoregames said: Te digo lo que haría yo. Siguiendo tu formula y para no complicarme mucho la vida, en vez de hacer que una corrutina se comunique con la otra, crearía un solo script, con una sola corrutina, en la que cada cierto tiempo (el cual seria equivalente a la cantidad de letras que tenga su dialogo), se muestre el texto de uno y luego el de el otro... si quieres te lo pongo en código para aclarar Si por favor, me gustaria hacerme una idea de como estructurarlo. Share this post Link to post Share on other sites
nomoregames 35 Report post Posted May 30, 2020 (edited) Aquí está un ejemplo de a lo qué me me refiero, le falta implementar lo de el tiempo que se alarga mas cuanto mas larga es la frase y algún arreglillo para hacer que la corrutina se detenga cuando ya no encuentre mas texto... si quieres mañana ya te lo escribo y lo comento para que sea entendible... bool ConversacionFinalizada = false; float time = 1; float actualTime; float DialogoALeer = 0; string DialogoActual; string DialogoALeerString; void Start() { StartCoroutine(ConversationManager()); } IEnumerator ConversationManager() { while (true) { if (ConversacionFinalizada == false) { if (actualTime < time) { actualTime += 0.001f + Time.deltaTime; } if (actualTime >= time) { actualTime = 0; DialogoALeer += 1; } } yield return null; } } void Actualizar() { Invoke("Dialogue" + DialogoALeer.ToString(), 0); print(DialogoActual); } void Dialogue0() { DialogoActual = "Hola"; Actualizar(); } void Dialogue1() { DialogoActual = ("Hola que tal?"); Actualizar(); } void Dialogue2() { DialogoActual = "Patata"; Actualizar(); } // Y así hasta el infinito y mas pa-cá espero que te sirva Edited May 31, 2020 by nomoregames 1 Share this post Link to post Share on other sites
iRobb 776 Report post Posted May 31, 2020 3 hours ago, nomoregames said: private void Update() { print(DialogoActual); Invoke("Dialogue" + DialogoALeer.ToString(), 0); } A ver @nomoregames, ya sé que intentas avanzar y todo eso. Puedes comentar porqué haces un Invoke en un Update? E inclusive, porqué en el Update llamas constantemente a la visualización de algo que no cambiará en cada frame? No sería mejor hacerlo en la coroutine cuando le toque? Sin acritud. 1 Share this post Link to post Share on other sites
francoe1 536 Report post Posted May 31, 2020 Este tipo de cosas son muy simples de diseñar y programar. Lo mejor en todo caso sería crear Scriptable Objects para crear la lógica de navegación de forma visual mediante referencia, los nodos sería un paso más avanzado. Lo más acertado sería leer los diálogos desde un archivo o múltiples archivos para separar mejor, esto permite el mantenimiento y la traducción con un coste bastante inferior. @nomoregames Tu idea esta bien, pero está mal implementada, debieras aprender a usar arreglos que justamente se utilizan para evitar este tipo de lógicas. Por otro lado muy importante es evitar el uso de Invoke ya que se trata de una implementación de reflexión. Share this post Link to post Share on other sites
nomoregames 35 Report post Posted May 31, 2020 @francoe1 Podrías poner un ejemplo en código? Donde irían los arreglos? Supongo que los usarías para substituir los métodos Dialogue0, Dialogue1, etc @iRobb 6 hours ago, iRobb said: Puedes comentar porqué haces un Invoke en un Update? E inclusive, porqué en el Update llamas constantemente a la visualización de algo que no cambiará en cada frame? Cierto, fui consciente de el error más tarde, pero estaba muy cansado así que lo dejé... pero ya está rectificado Share this post Link to post Share on other sites
J Montes 71 Report post Posted June 1, 2020 (edited) On 5/31/2020 at 5:56 AM, francoe1 said: @nomoregames Tu idea esta bien, pero está mal implementada, debieras aprender a usar arreglos que justamente se utilizan para evitar este tipo de lógicas. Por otro lado muy importante es evitar el uso de Invoke ya que se trata de una implementación de reflexión. Estoy de acuerdo. La sugerencia es buena y razonable, la implementación yaa.... no :). Pero bueno, no cabe duda de que @nomoregames vas avanzando. (Nota, @francoe1, en España si dices "arreglo" no te entiende nadie -aunque realmente es correcto, pero no se suele enseñar-, sugiero que usemos todos "array" para evitar confusión aquí). Dejémonos de ScriptableObjects y editores de nodos, la pregunta viene de alguien que está empezando con el tema diálogos y claramente necesita un consejo menos complejo. Usar archivos estaría bien pero nos preguntan por cómo secuenciar el diálogo así que pongámonos didácticos. Te pego un ejemplo en el que el diálogo está definido estáticamente en un array/arreglo como bien decía @francoe1, y con un uso razonable de la Coroutine. Molaría que ( @nomoregames y @overbaal ) lo leáis, lo probéis, y preguntéis cualquier cosa que no entendáis. He puesto las variables y comentarios en inglés porque eso es lo que recomiendo hacer a todo el mundo, pero si no entendéis algo, preguntad también. using System.Collections; using System.Collections.Generic; using UnityEngine; public class DialogManager : MonoBehaviour { /** * This class holds the information of each dialog line. * Could also include icons, colors or other information needed. */ public class DialogItem { public float duration; public string name; public string text; public DialogItem(float duration, string name, string text) { this.duration = duration; this.name = name; this.text = text; } } // Example initialization, but we could extend this class to read this from a file // or from wherever we need to. DialogItem[] dialogItems = new DialogItem[] { new DialogItem(2.0f, "Epi", "Y por fin he encontrado el Vespino"), new DialogItem(2.0f, "Blas", "que me ha de llevar a Santiago,"), new DialogItem(3.0f, "Epi", "y esta noche me espera el amor"), new DialogItem(2.0f, "Ana", "en Betanzos...") }; void Start() { // Start a dialog here as an example. // In an actual game, dialogs would be started from elsewhere calling this function. StartDialog(dialogItems); } /** * This starts a dialog. */ public void StartDialog(DialogItem[] dialogItems) { StartCoroutine(DialogManagerCoroutine(dialogItems)); } /* * This coroutine runs a dialog sequence and ends. * There are many ways to do this, this is a simple iterator over dialog items: */ IEnumerator DialogManagerCoroutine(DialogItem[] dialogItems) { int currentItemIndex = 0; // Loop over the dialog items until we are finished: while (currentItemIndex < dialogItems.Length) { // Grab the current dialog item DialogItem currentItem = dialogItems[currentItemIndex]; // Show it (we call a different function so we can change that) ShowDialogItem(currentItem); // Use "yield return new WaitForSeconds" in the coroutine to wait. This does not waste CPU cycles. yield return new WaitForSeconds(currentItem.duration); // Finally, increment current item. currentItemIndex++; } } /** * Show a single dialog item. In this example we just write to console. */ void ShowDialogItem(DialogItem item) { Debug.Log(item.name + "> " + item.text); } } Salida: ...y por favor (@nomoregames te miro a ti) intentad formatear el código bien. Ahí arriba hay muchísimas líneas en blanco sin sentido, a veces dobles o triples, y partes donde el código está mal indentado. También es cierto que el editor de la web no ayuda (la lía un poco con tab/spaces), hay que escribirlo en el editor de código y pegarlo aquí del tirón. Ya comentaréis ¡un saludo! Edited June 1, 2020 by J Montes 1 Share this post Link to post Share on other sites
nomoregames 35 Report post Posted June 1, 2020 (edited) @J Montes Osti, que currada, en cuanto pueda le voy a echar un muy buen rato para entenderlo todo.... muchas gracias 😄 PD; new DialogItem(2.0f, "Epi", "Y por fin he encontrado el Vespino"), new DialogItem(2.0f, "Blas", "que me ha de llevar a Santiago,"), new DialogItem(3.0f, "Epi", "y esta noche me espera el amor"), new DialogItem(2.0f, "Ana", "en Betanzos..."), new DialogItem(3.0f, "paco", "Pues yo soy más de extremoduro...") Buena referencia XD Así de primeras.... esto de aquí public class DialogItem Casi un año yebo con unity, mas de cinco personas explicándomelo y a día de hoy sigo sin entender esto de las clases... muy triste todo... Edited June 1, 2020 by nomoregames Share this post Link to post Share on other sites
leocub58 208 Report post Posted June 1, 2020 (edited) 12 hours ago, nomoregames said: Casi un año yebo con unity, mas de cinco personas explicándomelo y a día de hoy sigo sin entender esto de las clases... muy triste todo... Es algo normal si no estudias programación. Creo que te lo dije una vez pero, estaría bien que te hicieras un cursito. La clase es para crear un objeto con los valores de los parámetros de su constructor 13 hours ago, J Montes said: //esto es el constructor public DialogItem(float duration, string name, string text) { this.duration = duration;this.name = name;this.text = text; } 13 hours ago, J Montes said: new DialogItem(2.0f, "Epi", "Y por fin he encontrado el Vespino") Aquí esta creando el objeto, haciendo uso del constructor con los parámetros deaseados. Y ya por último en la corrutina utiliza las variables guardadas en memoria de cada objeto, como la duración, el nombre o el texto para imprimirlos en consola. Al final esta clase te permite una infinidad de cosas, por ejemplo podrías crear un método para editar el texto, el nombre o la duración directamente en el objeto. Edited June 1, 2020 by leocub58 Share this post Link to post Share on other sites
overbaal 5 Report post Posted June 1, 2020 Chicos al final he optado por el metodo de los nodos como me lo indica @leocub58, lo veo algo facil y simple de entender para lo que quiero hacer, ademas me permite iniciar eventos y tener mas variedad a la hora de dialogar con los npcs el propio jugador. Gracias por las ideas las tendre en cuenta para futuros proyectos! Share this post Link to post Share on other sites
AngelFG 15 Report post Posted June 1, 2020 12 hours ago, nomoregames said: @J Montes Osti, que currada, en cuanto pueda le voy a echar un muy buen rato para entenderlo todo.... muchas gracias 😄 PD; new DialogItem(2.0f, "Epi", "Y por fin he encontrado el Vespino"), new DialogItem(2.0f, "Blas", "que me ha de llevar a Santiago,"), new DialogItem(3.0f, "Epi", "y esta noche me espera el amor"), new DialogItem(2.0f, "Ana", "en Betanzos..."), new DialogItem(3.0f, "paco", "Pues yo soy más de extremoduro...") Buena referencia XD Así de primeras.... esto de aquí public class DialogItem Casi un año yebo con unity, mas de cinco personas explicándomelo y a día de hoy sigo sin entender esto de las clases... muy triste todo... Por si quieres mirarlo para un futuro, yo he creado un curso de POO. A lo mejor te ayuda en algo: https://wiki.cifprodolfoucha.es/index.php?title=Prog._Fundamentos_Programación_Orientada_a_Objetos_(POO) https://wiki.cifprodolfoucha.es/index.php?title=Prog._Aprendiendo_POO Share this post Link to post Share on other sites
TheShopKeeper 5 Report post Posted June 9, 2020 On 6/1/2020 at 5:23 PM, overbaal said: Chicos al final he optado por el metodo de los nodos como me lo indica @leocub58, lo veo algo facil y simple de entender para lo que quiero hacer, ademas me permite iniciar eventos y tener mas variedad a la hora de dialogar con los npcs el propio jugador. Gracias por las ideas las tendre en cuenta para futuros proyectos! Eso es un plugin para el xNode o ya viene predefinido en el assetpackage del xNode? Share this post Link to post Share on other sites
nomoregames 35 Report post Posted June 10, 2020 @TheShopKeeper Si lo que buscas es hacer las conversaciones mediante nodos, te recomiendo que utilices fungus https://assetstore.unity.com/packages/templates/systems/fungus-34184 es totalmente personaliza-ble, puedes todo tipo de conversaciones (desde tipo fallout hasta a algo más final fantasy) y tiene un foro de dudas que siempre esta activo No se cuanto tendrás avanzado, pero te valdrá le pena hacer el cambio. jeje, solo me falta decir algo como; llame ahora y le damos una batidora de regalo. Suerte. 2 Share this post Link to post Share on other sites