Jump to content
Sign in to follow this  
overbaal

ANSWERED Dialogos entre NPCS

Recommended Posts

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

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!

  • Like 1

Share this post


Link to post
Share on other sites

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
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

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 by nomoregames
  • Like 1

Share this post


Link to post
Share on other sites
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.

  • Like 1

Share this post


Link to post
Share on other sites

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

@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
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:

image.png

 

...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 by J Montes
  • Like 1

Share this post


Link to post
Share on other sites

 

@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 by nomoregames

Share this post


Link to post
Share on other sites
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 by leocub58

Share this post


Link to post
Share on other sites

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!

 

 

Screenshot_1.png

Share this post


Link to post
Share on other sites
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:

Share this post


Link to post
Share on other sites
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!

 

 

Screenshot_1.png

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

@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.

  • Like 2

Share this post


Link to post
Share on other sites
Sign in to follow this  

×
×
  • Create New...