Noticias

¡RECUERDA QUE SI ERES UN NUEVO USUARIO, DEBES PRESENTARTE PARA PODER PUBLICAR MENSAJES! | TENEMOS CANAL OFICIAL DE TELEGRAM: t.me/unity3dspain

Sistema de diálogo

Iniciado por Mega, Junio 27, 2017, 12:37:18 AM

Tema anterior - Siguiente tema
Hola quería saber cómo hacer que las letras de un texto se vallan poniendo una a una no todo a la vez.
 
No sé si me he explicado bien.
 
Gracias.

Cita de: Mega date=1498516638Hola quería saber cómo hacer que las letras de un texto se vallan poniendo una a una no todo a la vez.
   
   
      No sé si me he explicado bien.
   
   
      Gracias.
   


Vos podes tomar una strings y separarla, es decir que si podes tomar tantos caracteres y separarlos y crear varias cadenas a partir de una sola mas grande podes hacer lo que quieras con ellas. Podes de entrada separarlas, te da mejor control del dialogo, es decir empezas diciendo listo, no voy a tener mas de 50 caracteres por cuadro de dialogo, entonces podes crear algo asi para el tipico dialogo del NPC, el pasar el dialogo lo podes hacer con timers o con Inputs, o como quieras , la parte de datos se  suele llenar usando algun formato mas amigable como xml, JSON , etc, no desde el mismo start, pero para mostrarlo lo pongo aca nomas:
 

List<String> dialogoCompleto = new List<String>();
int dialogoActual = ;
public Text textoVisible;
void Start()
{
dialogoCompleto.Add("soy el primer cuadro de texto");
     dialogoCompleto.Add("soy el segundo cuadro de texto");
     dialogoCompleto.Add("soy el tercer cuadro de texto");
     textoVisible.text = dialogoCompleto[dialogoActual];
}
 
void Update()
{
if(Input.GetKeyDown(KeyCode.F)){
      dialogoActual++;
     
      if(dialogoActual == dialogoCompleto.Count){   //termino de pasar
        //desactivar y resetear el dialgo hasta que denuevo se lo muestre
      }else{
         textoVisible.text = dialogoCompleto[dialogoActual];
      }   
       
}
        
}

 
Si la queres separar o tomar hasta un determinado lugar y no las tenes previamente separadas tenes que usar algun metodo, hay bastante y bastante documentacion pero recuerdo los substring (de tal pos a tal pos) y los split (tomas strings separadas por algun caracter de interes, en tu caso este es el adecuado me parece)
 
Ej (no se si esta bien lo escribi al aire):
 

string completa = "AAA , BBB , CCC"
string[] separadas = completa.Split(',');
//separadas[0] --> "AAA"

 
Osea las tenes que separar de alguna forma.
 
saludos
 
 

Yo lo haria poniendo todo el texto y crearle una animación..
 

 
todo lo que esta en rojito le bajo el alpha(para que sea invisible) y palabra por palabra en el animator le voy subiendo el aplha(para que le de el efecto que quieres).

Cita de: Mega date=1498516638Hola quería saber cómo hacer que las letras de un texto se vallan poniendo una a una no todo a la vez.
   
   
      No sé si me he explicado bien.
   
   
      Gracias.
   


 
 
Lo que ha puesto @lightbug puede funcionar, pero creo que es más sencillo utilizar un IEnumerator, a parte la velocidad del texto dependerá del tiempo y no del frame rate:
 

   IEnumerator AnimarTexto(string textoCompleto)
    {
        int i = 0;
        text.text = "";
        while (i < textoCompleto.Length)
        {
            text.text += textoCompleto[i++];
            yield return new WaitForSeconds(0.02F);
        }
    }

 
Puedes modificar el tiempo de espera entre letras cambiando el WaitForSeconds. Para llamarlo solo tienes que escribir:
 

StartCoroutine(AnimarTexto(texto));

 
 

Cita de: TheBullet date=1498548406Lo que ha puesto @lightbug puede funcionar, pero creo que es más sencillo utilizar un IEnumerator, a parte la velocidad del texto dependerá del tiempo y no del frame rate:
   


Si fuera el unico caso de hacerlo "animado" es mas sencillo y visible con una corrutina, pero podes hacerlo independiente del frame rate tambien con update usando un Time.deltatime y tenes tambien el tiempo exacto. Por eso le puse que lo importante es separar las strings, el como lo reproduzca si es un evento temporal, o apretando una tecla para pasar o cualquier otro metodo es secundario.

Cita de: lightbug date=1498589715Si fuera el unico caso de hacerlo "animado" es mas sencillo y visible con una corrutina, pero podes hacerlo independiente del frame rate tambien con update usando un Time.deltatime y tenes tambien el tiempo exacto. Por eso le puse que lo importante es separar las strings, el como lo reproduzca si es un evento temporal, o apretando una tecla para pasar o cualquier otro metodo es secundario.
   


Si, se puede hacer con update poniendo una variable para que cuando pase el tiempo ponga la siguiente letra, pero parece más lioso. A parte, usando la corrutina podrías llamarla desde cualquier script para que te escriba un texto en pantalla... no se, yo creo que es mejor solución, aunque funcionará de ambas maneras. 

Últimamente estoy en plan evitar cualquier update 

Cita de: TheBullet date=1498604588A parte, usando la corrutina podrías llamarla desde cualquier script para que te escriba un texto en pantalla
   


Eso es relativo, si es public lo podes hacer con cualquier metodo sea corrutina o no.
 
 
 
Cita de: TheBullet date=1498604588Últimamente estoy en plan evitar cualquier update 


Yo pase exactamente por lo mismo, cambie todo lo temporal por corrutinas pero al poco tiempo retorne devuelta, para lo unico que las uso es para cargar cosas que depende de otras cosas, yieldiando una corrutina con otra es muy util en eso y no tenes que andar flageando una tarea con otra.
 
La razon por las que las cambie fue porque si tenia muchisimos objetos con sus corrutinas me comia performance (hablando de muuuchos objetos), ya que para cada corrutina hay un sistemita de fondo como un sub-proceso supongo, (tiene un nombre formal que no recuerdo), entonces como se me hacia mas facil usar un deltaTime y una variable time privada lo hice asi. Es mas de tanto usarlo se me hacia mas intuitivo verlo asi que con el yield waitforseconds. Pero da mas o menos lo mismo al final, yo porque trataba de saturar todo y hacer el "benchmark" y en mi caso gano el Update lo que es logico para el numero de objetos/corrutinas que meti.
 
Fijate un video de un tipo que hizo un "sistema de corrutinas propias" jaj no se como lo habra hecho, pero comparaba los picos de su sistema con las de Unity en el profiler y habia mucha diferencia, sobre todo habia picos en los comienzos de cada una y el framerate bajaba mucho. No recuerdo el nombre pero eran tres iniciales. Aunque me parece que para esta altura lo habran resuelto a este inconveniente, no lo se.

Cita de: lightbug date=1498610422Eso es relativo, si es public lo podes hacer con cualquier metodo sea corrutina o no.
   


Bueno pero si lo haces desde Update sería más lioso hacer que desde otro script el update hiciera aparecer el texto no?
 
 
 
Cita de: lightbug date=1498610422Yo pase exactamente por lo mismo, cambie todo lo temporal por corrutinas pero al poco tiempo retorne devuelta, para lo unico que las uso es para cargar cosas que depende de otras cosas, yieldiando una corrutina con otra es muy util en eso y no tenes que andar flageando una tarea con otra.
   
   
      La razon por las que las cambie fue porque si tenia muchisimos objetos con sus corrutinas me comia performance (hablando de muuuchos objetos), ya que para cada corrutina hay un sistemita de fondo como un sub-proceso supongo, (tiene un nombre formal que no recuerdo), entonces como se me hacia mas facil usar un deltaTime y una variable time privada lo hice asi. Es mas de tanto usarlo se me hacia mas intuitivo verlo asi que con el yield waitforseconds. Pero da mas o menos lo mismo al final, yo porque trataba de saturar todo y hacer el "benchmark" y en mi caso gano el Update lo que es logico para el numero de objetos/corrutinas que meti.
   
   
      Fijate un video de un tipo que hizo un "sistema de corrutinas propias" jaj no se como lo habra hecho, pero comparaba los picos de su sistema con las de Unity en el profiler y habia mucha diferencia, sobre todo habia picos en los comienzos de cada una y el framerate bajaba mucho. No recuerdo el nombre pero eran tres iniciales. Aunque me parece que para esta altura lo habran resuelto a este inconveniente, no lo se.
   


Interesante, creo que hace tiempo vi un asset en la store que era básicamente un sistema de corrutinas optimizadas. En mi proyecto actual siempre estoy mucho más limitado por la gráfica que por la cpu, así que tampoco me afecta en exceso si rinde un poco peor. Por curiosidad, ganaba por mucho el update?

Cita de: TheBullet date=1498638657Por curiosidad, ganaba por mucho el update?
   


Para pocos no, pero muchos objetos si, no tanto de forma constante sino los fps drops se veian cuando todas las corrutinas empezaban, no recuerdo bien que hice pero puse que todas hagan un waitForseconds(1) o algo asi, entonces las 1000/2000/4000 jaja arrancan y el pico era bestial. Lo probe hace como dos años.
 
Cita de: TheBullet date=1498638657Bueno pero si lo haces desde Update sería más lioso hacer que desde otro script el update hiciera aparecer el texto no?
   


Yo lo tendria algo asi ponele:
 

//DialogoManager
public Text m_textTarget;
//...
//...
float m_time = ;
bool m_activated = false;
string[] m_completeDialog;
int currentDialog = ;
//desde otro scripts llamo a ShowText y le paso el dialogo completo
public void ShowText(string completeDialog)
{
// m_completeDialog <---- Separo completeDialog en strings para el array
    m_activated = true;
}
void Update()
{
if(!activated)
   return;
if(m_time > ){
       //Muestro el currentDialog Texto en el targetText UI
         m_time -= Time.deltaTime;
    }else{
      currentDialog++;
      if(currentDialog == m_completeDialog.Length)
       //Si ya paso el ultimo desactivo el dialogo y reseteo todo
      else
         //Si no, paso a la proxima string reseteo time
    }
             
}

 
Lo hice asi nomas asi que no si ni si corre , pero fijate que si cambio el Update por un Ienumarator con public y ""masomeno"" que tengo la corrutina entera, el segundo if else lo podes hacer con un for en la corrutina para emprolijarlo, o con un while, cosa que en Update no se podria. El primero no lo tendrias, y el segundo es para llevar cuenta del tiempo, tampoco lo tendrias.
 
Es cierto la corrutina se ve mejor y estan centradas en "humanizar" este tipo de cosas, sobre todo eventos temporales. Fijate que hay un vid de youtube de como pasar todo a corrutinas, una charla, es muy bueno. Pero igual en este caso tampoco es tanto lio, ya con estas pocas lineas podes hacerte un manager de dialogo entero obvio hay mejorar aqui y alla.
 
el otro script ese que mencionas puede hacer aparecer el texto, pero en mi caso prefiero que un script(manager) sea el encargado de mostrar textos (como este), controlar sus animaciones, sonidos, etc,etc y los otros scripts le pasen el dato por ejemplo la string "completeDialog". O puede ser que este mismo contenga todos los dialogos del Juego en su JSON o Xml, y dependiendo de quien con quien interactua (y en que momento del juego quizas) busque en su base de datos y aparezca el dialogo, tipico de aventura grafica.

Cita de: lightbug date=1498679397Para pocos no, pero muchos objetos si, no tanto de forma constante sino los fps drops se veian cuando todas las corrutinas empezaban, no recuerdo bien que hice pero puse que todas hagan un waitForseconds(1) o algo asi, entonces las 1000/2000/4000 jaja arrancan y el pico era bestial. Lo probe hace como dos años.
   
   
      Yo lo tendria algo asi ponele:
   
   

//DialogoManager
public Text m_textTarget;
//...
//...
float m_time = ;
bool m_activated = false;
string[] m_completeDialog;
int currentDialog = ;
//desde otro scripts llamo a ShowText y le paso el dialogo completo
public void ShowText(string completeDialog)
{
// m_completeDialog <---- Separo completeDialog en strings para el array
    m_activated = true;
}
void Update()
{
if(!activated)
   return;
if(m_time > ){
       //Muestro el currentDialog Texto en el targetText UI
         m_time -= Time.deltaTime;
    }else{
      currentDialog++;
      if(currentDialog == m_completeDialog.Length)
       //Si ya paso el ultimo desactivo el dialogo y reseteo todo
      else
         //Si no, paso a la proxima string reseteo time
    }
             
}

   
      Lo hice asi nomas asi que no si ni si corre , pero fijate que si cambio el Update por un Ienumarator con public y ""masomeno"" que tengo la corrutina entera, el segundo if else lo podes hacer con un for en la corrutina para emprolijarlo, o con un while, cosa que en Update no se podria. El primero no lo tendrias, y el segundo es para llevar cuenta del tiempo, tampoco lo tendrias.
   
   
      Es cierto la corrutina se ve mejor y estan centradas en "humanizar" este tipo de cosas, sobre todo eventos temporales. Fijate que hay un vid de youtube de como pasar todo a corrutinas, una charla, es muy bueno. Pero igual en este caso tampoco es tanto lio, ya con estas pocas lineas podes hacerte un manager de dialogo entero obvio hay mejorar aqui y alla.
   
   
      el otro script ese que mencionas puede hacer aparecer el texto, pero en mi caso prefiero que un script(manager) sea el encargado de mostrar textos (como este), controlar sus animaciones, sonidos, etc,etc y los otros scripts le pasen el dato por ejemplo la string "completeDialog". O puede ser que este mismo contenga todos los dialogos del Juego en su JSON o Xml, y dependiendo de quien con quien interactua (y en que momento del juego quizas) busque en su base de datos y aparezca el dialogo, tipico de aventura grafica.
   


 
 
Si hay muchos objetos, la clave para las corrutinas supongo que es hacer una cola para que se inicien X corrutinas a cada frame para evitar picos y después hacer un tiempo de espera de varios frames como mínimo para ahorrar procesamiento. Supongo que si las usas como un Update utilizando "yield return null" acaba siendo una tontería, porque para eso está el Update.

Cita de: lightbug date=1498519060la parte de datos se  suele llenar usando algun formato mas amigable como xml, JSON , etc,
   


HOLA. Estaba leyendo y me pareció interesante ésto.

En mi caso quiero usar un .json para guardar los diálogos, pero busco orientación. He visto vídeos, pero no me intero. Tienes más info? :O

Cita de: Null date=1499417145HOLA. Estaba leyendo y me pareció interesante ésto.

      En mi caso quiero usar un .json para guardar los diálogos, pero busco orientación. He visto vídeos, pero no me intero. Tienes más info? :O
   


Hola Null, podes crearte tus JSON hoy en dia con un editor online si quisieras, ej : http://jsoneditoronline.org/
 
La idea es crearte un arreglo de objetos, dialogos maestros, que contienen a los dialogos propiamente dichos en forma de strings, es decir creas arreglos de strings, que se yo, es una idea.
 
Te quedaria algo asi, aunque te digo no recuerdo muy bien la notacion de JSON, seguro esta mal, pero a maaas o menos:
 

{
  "Dialogo 1": [
    "blabla 1",
    "blabla 2"
  ],
  "Dialogo 2": [
    "blabla 1",
    "blabla 2"
  ]
}

 
Lo te que quedaria hacer es agarrar la string del .json, luego leer los arreglos de strings y guardarlos para luego usarlos, nunca lo hice pero seguro no debe de haber mucha historia ... creo
 
 

Echadle un ojo a un Asset de la Store llamado "UI Text Extensions", ó "UI Text FX". Trae varios ejemplos de cómo hacer un estilo mecanografiado letra a letra o palabra a palabra...

 
 
Cita de: Null date=1499417145HOLA. Estaba leyendo y me pareció interesante ésto.

      En mi caso quiero usar un .json para guardar los diálogos, pero busco orientación. He visto vídeos, pero no me intero. Tienes más info? :O
   


Uh algo que se me Re paso, podes usar Scirptable Objects para los dialogos, que se yo tenes un SCO dedicado a un dialogo completo, que tome distintos personajes, con sus strings, y las vas agregando "al vuelo" = en inspector. Podes tener otro SCO que contenga todos los "SCO dialogo" anteriores, o podes cargarlos directamente via Resources si quisieras, los caminos son varios, depende de la creatividad/conveniencia de cada uno.

Hola yo lo e conseguido asi esta en js pero igual te sirve
 

var mensaje : UI.Text;
var texto : String;
function Start () {
StartCoroutine(dictado(texto));

}
function Update () {


}
function dictado (frase : String){

var letra : int = 0;
mensaje.text ="";
while ( letra < frase.length){

   mensaje.text += frase[letra];
   letra += 1;
   yield WaitForSeconds(0.02f);

}

}

 
 

Etiquetas: