Saltar al contenido principal

CommandGraph: scripting de eventos basado en nodos

El CommandGraph es el sistema de scripting visual de MCE para crear comportamientos de NPC, escenas, misiones y eventos interactivos. Ofrece un editor basado en nodos donde conectas comandos para definir secuencias de eventos, sin necesidad de código C#.

Es la herramienta principal para los diseñadores de juegos que trabajan con MCE en todas las ediciones, incluidas las ediciones compiladas en las que el código fuente no se incluye.

Lo que produce un grafo

Ese cuadro es la salida de un grafo de dos nodos: un cartel con el que el jugador interactuó y un comando ShowSignDialog. Nada de eso se escribió en C#: la misma forma escala a una escena con ramificaciones, y el runtime no distingue la diferencia.

¿Qué es CommandGraph?​

Un CommandGraph (ActorCommandGraph) es un grafo de nodos guardado en un Actor (cualquier entidad interactuable del mundo). Cuando se activa el actor, el grafo se ejecuta como una corrutina, un nodo tras otro.

Todo actor tiene varias ranuras de grafo, una por cada momento en el que quieras reaccionar:

RanuraSe ejecuta
On Enable Command GraphCuando el actor se activa.
Loop Command GraphUna y otra vez, mientras no se esté ejecutando otro grafo del actor.
Interact Command GraphCuando el jugador interactúa con el actor.
On Demand Command Graph 0 to 3Solo cuando otro grafo lo pide (RunOnDemand, RunMultipleOnDemand).

Los actores especializados agregan sus propias ranuras: TriggerActor tiene los grafos "el jugador está a punto de entrar / entró / está a punto de ser teletransportado / fue teletransportado" y "un actor fue empujado dentro", ActorCharacter tiene el grafo "spot player" y PushableActor tiene el grafo "push".

Piensa en un grafo como un script visual donde cada nodo es una acción del juego:

[Root] → [ShowDialog] → [IfPlayerHasBadge]
├─ True → [GivePlayerItem] → ...
└─ False → [ShowDialog: "Come back later"]

Crear tu primer evento​

Paso 1: Crear un actor​

La forma más rápida es el menú de la Jerarquía: haz clic derecho y elige GameObject > MCE > uno de los actores ya preparados:

MenúCrea
Blank/Character, Blank/EmptyTrigger, Blank/InvisibleUn personaje, disparador o actor invisible vacío para que lo rellenes tú
NPCs/Simple dialog, NPCs/Give item, NPCs/Give monsterUn NPC con un grafo listo de diálogo, regalo de objeto o regalo de monstruo
Trainers/Static, Circle, Look around, Random look around, Random walkEntrenadores con los comportamientos habituales
Other/Sign, Pick up item, árboles cortables, rocas rompibles, rocas empujables, remolinosLos elementos clásicos del mundo

También puedes agregar el componente tú mismo. Los tipos de actor concretos son:

Tipo de actorDisparadorCaso de uso
SimpleActorEl jugador interactúa (sin gráficos ni lógica extra)Puntos de interacción invisibles
ActorCharacterEl jugador interactúa; puede caminar, mirar alrededor y detectar al jugadorNPCs, entrenadores
TriggerActorEl jugador pisa sobre él (no bloquea el movimiento)Disparadores automáticos, warps, eventos ocultos
ActorItemEl jugador interactúa, entrega su objeto y desapareceObjetos recogibles del suelo
PushableActorEl jugador lo empuja (es un ActorCharacter)Rocas, bloques de puzles

Actor y GridSubscribingActor son clases base abstractas; no las agregas directamente.

Paso 2: Abrir el editor de CommandGraph​

  1. Selecciona el GameObject del actor.
  2. En el Inspector, busca la ranura de grafo que quieras (por ejemplo Interact Command Graph).
  3. Haz clic en Edit graph para abrir la ventana del editor de nodos. Delete graph lo vacía.

Paso 3: Agregar nodos​

  1. Haz clic derecho en el editor de grafos.
  2. Elige Create Command / <Categoría> / <Nodo>. La categoría es la carpeta del nodo (ver abajo).
  3. Conecta los nodos arrastrando desde el puerto de salida de un nodo al puerto de entrada de otro.

Paso 4: Configurar los nodos​

Haz clic en un nodo para editar sus campos en el panel del Inspector: el texto de un diálogo, el objeto y la cantidad de un regalo, el tile de un teletransporte, la variable de una condición.

Categorías de nodos​

Estas son las categorías tal como aparecen en el menú Create Command. La lista de abajo nombra los nodos más útiles de cada una; el conjunto completo está en el menú.

Dialogs​

NodoDescripción
ShowDialogMuestra un diálogo común
ShowChoiceDialogMuestra un diálogo en el que el jugador elige (un puerto de salida por opción)
ShowSignDialogMuestra un diálogo de cartel
ShowNoSkippableDialogMuestra un diálogo que el jugador no puede saltar
NextDialogSalta al siguiente diálogo
ShowUsedMoveDialogUn diálogo que indica que un monstruo usó un movimiento
ShowMonsterPicturePone la imagen frontal de un monstruo en una ventana enmarcada, o la quita

Variables​

Condiciones y cambios de variables. Cada nodo If... tiene dos puertos de salida, True y False.

NodoDescripción
SetBoolVariable, SetIntVariableEstablece una variable de juego
IfBool, IfIntEquals, IfIntCompareRamifica según un booleano o un entero comparado con un valor (menor, mayor, igual...)
IfIntVariablesCompareCompara una variable entera con otra variable entera
SwitchIntVariableUn puerto de salida por cada valor de una variable entera
WhileBool, WhileConditionRepite mientras se cumpla una condición
IfPlayerCharacterIs, IfPlayerDirectionIsRamifica según el personaje jugador elegido o la dirección a la que mira
SetTemporalBoolVariable, SetTemporalIntVariable, IfTemporalBoolVariables del actor en ejecución que no se guardan con la partida

Las variables de juego se eligen mediante una referencia de variable (el almacén global o el de una escena). Persisten en los datos de guardado y se pueden leer desde cualquier grafo o script.

Items​

NodoDescripción
GivePlayerItem, TakePlayerItemAgrega o quita un objeto de la mochila del jugador
GivePlayerMoneyDa dinero al jugador
IfPlayerHasItemRamifica según si el jugador tiene un objeto
ChooseItemDialogPide al jugador que elija un objeto y ejecuta comandos en consecuencia

Monsters​

NodoDescripción
GiveMonstersDa monstruos al jugador (especie fija o aleatoria). Necesita un grant id en la capa en línea: ver Regalos de monstruos
HealPlayerRosterCura a todo el equipo
ChooseMonsterDialog, ChooseTwoMonstersDialogPide al jugador que elija uno o dos monstruos
ChangeMonsterNickname, RemoveMonsterNicknameRenombra un monstruo
MoveTutor, RemindPreviouslyLearntMovesEnseña un movimiento o recuerda movimientos anteriores
IfMonsterCanLearnMove, IfRosterHasMoveRamifica según los movimientos
OpenStorageAbre el almacenamiento de monstruos

Battles​

NodoDescripción
SingleTrainerFightLucha contra un solo entrenador
SingleWildFight, DoubleWildFightDispara una lucha contra monstruos salvajes
FightFromTemplateLanza una lucha a partir de una plantilla de batalla
RandomFightAgainstRandomRostersUna lucha aleatoria contra uno o dos equipos aleatorios
StartTowerRunInicia una carrera de la Torre de Batalla
IfCanHaveDoubleBattleRamifica según si es posible una batalla doble

Badges, Dex, Quests​

NodoDescripción
GiveBadge, IfPlayerHasBadgeDa una medalla / comprueba si se tiene
GiveDex, IfPlayerHasDex, IfDexIsComplete, RegisterMonsterAsSeenGestión de la dex
StartQuest, UpdateQuestObjective, ProgressQuestObjective, CompleteQuest, FailQuestProgreso de misiones (ver Sistema de misiones)
IfPlayerHasQuest, IfCompletedQuest, IfQuestFailed, IfCurrentQuestObjectiveRamifica según el estado de la misión

Animations​

Personajes, el jugador y la pantalla.

NodoDescripción
Move, MovePlayer, WalkToPlayerHace caminar a un personaje, al jugador, o hacia el jugador
Look, LookAtPlayer, ForcePlayerToLookGira a un personaje
JumpCharacter, WanderWithinRangeSalta; deambula alrededor de un tile inicial
HideCharacter, ShowCharacter, HidePlayer, ShowPlayerMuestra u oculta gráficos
MoveFollower, LookFollowerHace caminar o girar al monstruo que sigue al jugador
FadeScreenToBlack, OpenDoorFunde la pantalla a negro; abre una puerta en el tile del actor
PlayExclamation, PlayEmotionMuestra un globo sobre un personaje: ver Globos de emoción y emotes

Sounds​

NodoDescripción
PlayMusic, StopMusic, SaveMusic, RestoreSceneMusicMúsica del mundo por encima de la propia del mapa
PlaySound, PlayMonsterCry, WaitForAudioSonidos y gritos

Shops, Trade, Saves, Breeding​

NodoDescripción
BuyInShop, SellInShopEjecuta la lógica de la tienda para comprar o vender
TradeSelectedMonsterIntercambia el monstruo que el jugador eligió
AutoSaveIfEnabledGuarda automáticamente si está activado en la configuración
StoreTwoSelectedMonstersInNursery, IfEggIsReady, BreedEggInNurseryAndGiveToPlayerLa guardería

Utils​

NodoDescripción
TeleportPlayerTeletransporta al jugador a otra ubicación (validado por el servidor cuando hay conexión)
TeleportActorInsideScene, PlaceActorMueve un actor dentro de la escena actual
WaitTime, LoopXTimes, RunInParallelTemporización y flujo
LockPlayerInputBloquea o desbloquea el movimiento del jugador durante una escena
SetActorActive, AutoDestroyApaga otro objeto, o destruye el actor
SwitchOnDayMoment, SwitchTimeOfDayRamifica según el momento del día, o lo establece
SetLastHealLocation, SetLastHealLocationToCurrentDónde reaparece el jugador tras perder
LogMessageRegistra un mensaje en la consola

Conectar nodos​

El CommandGraph usa un modelo de conexión basado en flujo:

  • Cada grafo empieza en un nodo Root.
  • Cada nodo tiene un puerto de entrada y uno o más puertos de salida.
  • La mayoría de los nodos tiene exactamente un puerto de salida (el siguiente comando). Los nodos If... tienen True y False; ShowChoiceDialog tiene un puerto por opción; SwitchOnDayMoment tiene uno por momento del día.
  • Un nodo sin puerto de salida conectado termina esa rama del grafo.

Ejemplo: NPC de tienda​

[Root]
→ [ShowDialog: "Welcome! Would you like to browse my wares?"]
→ [ShowChoiceDialog: "Buy" / "Sell" / "No thanks"]
├─ "Buy" → [BuyInShop]
├─ "Sell" → [SellInShop]
└─ "No thanks" → [ShowDialog: "Come back anytime!"]

Ejemplo: quien da una misión​

[Root]
→ [IfBool: rescued_lost_monster]
├─ True → [IfBool: quest_reward_given]
│ ├─ True → [ShowDialog: "Thanks again!"]
│ └─ False → [GivePlayerItem: TM, 1]
│ → [SetBoolVariable: quest_reward_given = true]
│ → [ShowDialog: "Take this as thanks!"]
└─ False → [ShowDialog: "Please help me find my lost monster!"]
→ [SetBoolVariable: quest_find_monster = true]

Ejemplo: líder de gimnasio​

[Root]
→ [IfPlayerHasBadge: Boulder Badge]
├─ True → [ShowDialog: "You've already proven yourself!"]
└─ False
→ [ShowDialog: "I am the Gym Leader! Prepare for battle!"]
→ [SingleTrainerFight]
├─ On Player Won → [ShowDialog: "Impressive! You've earned this."]
│ → [GiveBadge: Boulder Badge]
└─ On Player Lost → [ShowDialog: "Train harder and come back!"]

SingleTrainerFight tiene tres puertos de salida: el puerto simple del siguiente comando, On Player Won y On Player Lost. La rama "lost" solo se ejecuta cuando el nodo está configurado para no reaparecer al jugador tras una derrota.

Probar eventos​

  1. Entra en Play Mode en el editor.
  2. Camina con tu personaje hasta el actor.
  3. Pulsa el botón de interacción.
  4. El grafo se ejecuta y puedes ver el flujo.
Depurar un grafo

Si un grafo no se comporta como esperabas:

  1. Revisa la Consola en busca de errores.
  2. Verifica que existan las variables de juego, objetos y monstruos referenciados.
  3. Asegúrate de que todos los puertos de salida estén conectados: un puerto sin conectar termina esa rama en silencio.
  4. Agrega un nodo LogMessage para imprimir valores durante la ejecución.

Buenas prácticas​

  1. Nombra tus actores de forma descriptiva. "NPC_Professor_Lab" es mejor que "Actor (3)".
  2. Usa variables de juego para el estado. No te apoyes solo en activar/desactivar actores.
  3. Prueba ambas ramas. Cada nodo If... debe funcionar para True y para False.
  4. Mantén los grafos legibles. Usa la disposición espacial para aclarar el flujo. Agrupa los nodos relacionados.
  5. Reutiliza patrones. Cuando tengas un NPC de tienda que funcione, duplícalo y modifícalo para otras tiendas.
  6. Guarda antes de probar. Los cambios del CommandGraph son cambios a nivel de escena que se pueden perder si Unity se cierra de forma inesperada.

Para la parte de C# (ejecutar un grafo desde código o escribir tu propio nodo), consulta la API de CommandGraph.