Aprende a detener por completo el movimiento de un NPC mientras hablas con él en Unity, manteniendo una lógica simple, genérica y reutilizable en C#. Con una sola variable booleana y una verificación del estado del DialogManager, tendrás diálogos fluidos y personajes que se comportan de forma coherente.
¿Cómo pausar el movimiento del NPC al iniciar un diálogo?
Para evitar que el NPC “se escape” durante la conversación, agrega una variable booleana que indique si está hablando. Con eso, el flujo del Update se corta con un simple return cuando el diálogo está activo. Así, evitas ejecutar la lógica de caminar.
Usa una variable booleana: isTalking.
Coloca la comprobación al inicio de Update.
Llama a tu método de parada: StopWalking().
Termina el Update con return para no procesar caminar.
// NPCMovement.csusingUnityEngine;publicclassNPCMovement:MonoBehaviour{publicbool isWalking;publicbool isTalking;// false por defecto.privateDialogManager manager;voidStart(){ manager =FindObjectOfType<DialogManager>();}voidUpdate(){// Si el diálogo ya terminó, deja de "estar hablando".if(manager !=null&&!manager.dialogActive){ isTalking =false;}// Si está hablando, se detiene en seco y no ejecuta nada más.if(isTalking){StopWalking();return;}// Resto de la lógica de caminar/parar aleatoriamente...// ...}voidStopWalking(){// Implementación existente para detener movimiento.}}
¿Qué cambios aplicar en NPC Movement y NPC Dialog?
La clave es comunicar el inicio del diálogo desde el script del diálogo hacia el de movimiento, y hacerlo de forma genérica. Usa GetComponentInParent para encontrar el componente de movimiento en el objeto padre solo si existe.
¿Qué modificar en NPC movement?
Declara isTalking junto a isWalking.
Añade la referencia al DialogManager con FindObjectOfType.
Controla el flujo con if (isTalking) { StopWalking(); return; }.
¿Cómo comunicar el diálogo con el movimiento?
Desde el script del diálogo, al iniciar la conversación, verifica si el NPC tiene el componente de movimiento en el padre.
Si lo tiene, marca isTalking = true.
// NPCDialog.cs (fragmento dentro del momento en que inicias el diálogo)usingUnityEngine;publicclassNPCDialog:MonoBehaviour{voidTryStartDialog(){// Aquí ya has detectado que el jugador está en zona y ha pulsado *Intro*.// Se ha notificado al manager para mostrar el diálogo.var movement =GetComponentInParent<NPCMovement>();// Ojo: in parent.if(movement !=null){ movement.isTalking =true;// El NPC se detiene durante el diálogo.}}}
Esta verificación asegura un diseño genérico: cualquier NPC puede tener diálogo, y solo los que se muevan serán detenidos.
Mantienes la lógica separada: el script de diálogo no mueve, solo informa; el de movimiento decide parar o seguir.
¿Cómo reanudar el movimiento tras finalizar el diálogo?
Cuando el DialogManager indique que el diálogo ya no está activo, simplemente desactiva isTalking. La lógica de caminar se reanudará automáticamente.
Comprueba el estado del DialogManager en cada Update.
Si !manager.dialogActive, pon isTalking = false.
Al no cumplirse el if (isTalking), el NPC vuelve a su ciclo de caminar/parar.
// Dentro de NPCMovement.Update()if(manager !=null&&!manager.dialogActive){ isTalking =false;// El diálogo terminó, se puede volver a caminar.}
¿Qué habilidades y keywords te llevas?
Uso de booleans para control de estado: isWalking, isTalking.
Gestión de flujo en Update: return temprano para evitar lógica innecesaria.
Comunicación entre componentes con GetComponentInParent.
Referencias globales con FindObjectOfType al DialogManager.
Diseño genérico: diálogo para todos los NPCs, movimiento solo para quienes tengan el componente.
Interacción contextual: zona de activación y botón Intro para iniciar diálogo.
¿Quieres ir un paso más allá? Implementa la misma idea para tu propio personaje jugador y evita que se mueva mientras conversa con otro NPC. Comparte tu enfoque y resultados en comentarios.
Yo hice que el conejito se moviera una vez el player salga de la zona de diálogo con la función OnTriggerExit2D.
Para el caso del player no he limitado el movimiento, si no que mas bien lo he dejado mal educado jaja pero si sale de la zona del NPC, ejecuto HideDialog() para desactivar y resetear el dialogo:
NPCDialog.cs
En cuanto al NPC, solo desactivo su movimiento si isActive de DialogManager es true:
NPCMovement.cs
Chicos, agregando 4 lineas se hace todo. Cuando el dialogo está activo pongo que el Time.timeScale = 0.
Si el dialogo no está activo lo pongo de nuevo en 1 y listo.
El Time.timeScale maneja todas las fisicas del juego. Con lo cual si lo ponemos a 0 se congela todo.
Para detener al player cree una referencia al DialogueManager:
.
.
La definí en el start:
.
.
Y comprobé su estado para saber si el personaje podía moverse o no:
.
Genial
Considero mucho más simple que al entrar en la zona del NPC este desactive su script NPCMovement, tambien como tengo la lógica del movimiento del jugador en un script aparte, desactivo esta lógica solo cuando se encuentra en dialogo. Asi nos evitamos mezclar lógicas en scripts y todo se mantiene en el manager.
Yo lo resolví solo verificando si esta activo algún dialog en donde recibe las instrucciones para caminar. Esto solo editando el PlayerController
//Creé esta variable y la pueden dejar asinada desde el start canWalk=GameObject.FindObjectOfType<DialogManager>().dailogActive;if((Mathf.Abs(Input.GetAxisRaw(HORIZONTAL))>0.5f||Mathf.Abs(Input.GetAxisRaw(VERTICAL))>0.5f)&&!canWalk){ walking=true; lastMovement=newVector2(Input.GetAxisRaw(HORIZONTAL),Input.GetAxisRaw(VERTICAL)); playerRigidbody.velocity=lastMovement.normalized* speed*Time.deltaTime;}