Saltearse al contenido

Crear un NPC Personalizado

Objetivo

Crear un Slime — un NPC hostil que persigue y ataca a los jugadores en cuanto los ve. Configurarás un modelo 3D con animaciones, definirás su comportamiento de IA mediante herencia de plantillas, configurarás una tabla de botín con pesos y añadirás traducciones multilingües. Al final, tendrás un mod de NPC completamente funcional que podrás invocar en el Modo Creativo.

Lo Que Aprenderás

  • Cómo se estructuran los NPCs a través de tres capas JSON (Modelo de Servidor, Rol de NPC, Tabla de Botín)
  • Cómo configurar un modelo con 9 conjuntos de animaciones
  • Cómo la herencia de plantillas (Template_Predator) proporciona el comportamiento de IA
  • Cómo las tablas de botín con pesos controlan el loot
  • Cómo añadir traducciones para EN, ES y PT-BR

Requisitos Previos

Repositorio del mod complementario: hytale-mods-custom-npc


Descripción General de la Arquitectura de NPCs

A diferencia de los bloques y objetos que usan un único archivo JSON cada uno, los NPCs requieren tres definiciones separadas que trabajan juntas:

flowchart TD;
A[Modelo de Servidor<br>Modelo + Animaciones + HitBox] --> D[NPC en el Juego];
B[Rol de NPC<br>Comportamiento IA + Estadísticas] --> D;
C[Tabla de Botín<br>Loot al Morir] --> D;
style A fill:#2d6a8f,color:#fff;
style B fill:#2d5a27,color:#fff;
style C fill:#8f6a2d,color:#fff;
style D fill:#5a2d8f,color:#fff;
CapaUbicación del ArchivoPropósito
Modelo de ServidorServer/Models/Vincula el archivo .blockymodel, la textura, las animaciones, el hitbox y la configuración de cámara
Rol de NPCServer/NPC/Roles/Define el comportamiento de IA mediante herencia de plantillas, salud, retroceso y claves de traducción
Tabla de BotínServer/Drops/Controla qué loot se suelta cuando el NPC muere, usando selección aleatoria con pesos

El nombre de Appearance del Modelo de Servidor conecta las tres capas — el Rol de NPC lo referencia, y el motor lo usa para encontrar el modelo, la textura y las animaciones correctas.


Paso 1: Crear el Modelo y la Textura en Blockbench

Abre Blockbench y crea un nuevo proyecto de Hytale Character:

  • Block Size: 64
  • Pixel Density: 64
  • UV Size: 128×128 (la textura debe coincidir: 128×128 píxeles)

Construye el cuerpo del slime usando cubos organizados en grupos. Para el Slime, la estructura es:

GrupoPropósito
BodyCuerpo principal del slime (cubo grande)
HeadPorción superior (usada por el seguimiento de cámara)
EyesDetalles de la cara
Arm_Left / Arm_RightPequeños apéndices para animaciones de ataque
Leg_Left / Leg_RightBases para animaciones de caminar

Pinta la textura en la pestaña Paint — tonos verdes con manchas más oscuras funcionan bien para una criatura tipo slime.

Modelo de Slime en Blockbench — cuerpo basado en cubos con ojos y boca

Exportar el Modelo

  1. File > Export > Export Hytale Blocky Model → guardar como Model_Slime.blockymodel
  2. Guardar la textura por separado como Texture.png (128×128)

Crear Animaciones

Los NPCs necesitan archivos de animación para cada estado de movimiento. Crea estas 9 animaciones en la pestaña Animate de Blockbench:

AnimaciónArchivoBuclePropósito
IdleIdle.blockyanimEstar quieto — rebote sutil
WalkWalk.blockyanimMoverse hacia adelante
Walk_BackwardWalk_Backward.blockyanimMoverse hacia atrás
RunRun.blockyanimPerseguir al jugador
AttackAttack.blockyanimGolpe cuerpo a cuerpo
DeathDeath.blockyanimNoSe reproduce una vez al morir
CrouchCrouch.blockyanimInactivo agachado
Crouch_WalkCrouch_Walk.blockyanimAvanzar agachado
Crouch_Walk_BackwardCrouch_Walk_Backward.blockyanimRetroceder agachado

Exporta cada animación con File > Export > Export Hytale Block Animation.


Paso 2: Configurar la Estructura de Archivos del Mod

Coloca tus archivos en la carpeta del mod siguiendo esta estructura exacta:

CreateACustomNPC/
├── manifest.json
├── Common/
│ ├── Icons/
│ │ └── ModelsGenerated/
│ │ └── Slime.png
│ └── NPC/
│ └── Beast/
│ └── Slime/
│ ├── Model/
│ │ ├── Model_Slime.blockymodel
│ │ └── Texture.png
│ └── Animations/
│ └── Default/
│ ├── Idle.blockyanim
│ ├── Walk.blockyanim
│ ├── Walk_Backward.blockyanim
│ ├── Run.blockyanim
│ ├── Attack.blockyanim
│ ├── Death.blockyanim
│ ├── Crouch.blockyanim
│ ├── Crouch_Walk.blockyanim
│ └── Crouch_Walk_Backward.blockyanim
├── Server/
│ ├── Models/
│ │ └── Beast/
│ │ └── Slime.json
│ ├── NPC/
│ │ └── Roles/
│ │ └── Slime.json
│ ├── Drops/
│ │ └── Drop_Slime.json
│ └── Languages/
│ ├── en-US/
│ │ └── server.lang
│ ├── es/
│ │ └── server.lang
│ └── pt-BR/
│ └── server.lang

Todas las rutas en Common/ deben comenzar con una raíz permitida: NPC/, Icons/, Items/, Blocks/, etc. El modelo y las animaciones van bajo NPC/, y el icono de aparición va bajo Icons/.


Paso 3: Crear el manifest.json

{
"Group": "HytaleModdingManual",
"Name": "CreateACustomNPC",
"Version": "1.0.0",
"Description": "Implements the Create A NPC tutorial with a custom slime",
"Authors": [
{
"Name": "HytaleModdingManual"
}
],
"Dependencies": {},
"OptionalDependencies": {},
"IncludesAssetPack": true,
"TargetServerVersion": "2026.02.19-1a311a592"
}

Paso 4: Definir el Modelo de Servidor

El Modelo de Servidor es el puente entre los assets 3D en Common/ y el motor del juego. Le indica a Hytale dónde encontrar el modelo, la textura y cada animación.

Crea Server/Models/Beast/Slime.json:

{
"Model": "NPC/Beast/Slime/Model/Model_Slime.blockymodel",
"Texture": "NPC/Beast/Slime/Model/Texture.png",
"EyeHeight": 1.5,
"CrouchOffset": -0.15,
"HitBox": {
"Max": { "X": 0.8, "Y": 2.0, "Z": 0.8 },
"Min": { "X": -0.8, "Y": 0, "Z": -0.8 }
},
"Camera": {
"Pitch": {
"AngleRange": { "Max": 15, "Min": -15 },
"TargetNodes": ["Head"]
},
"Yaw": {
"AngleRange": { "Max": 15, "Min": -15 },
"TargetNodes": ["Head"]
}
},
"AnimationSets": {
"Walk": {
"Animations": [
{ "Animation": "NPC/Beast/Slime/Animations/Default/Walk.blockyanim" }
]
},
"Attack": {
"Animations": [
{ "Animation": "NPC/Beast/Slime/Animations/Default/Attack.blockyanim" }
]
},
"Idle": {
"Animations": [
{ "Animation": "NPC/Beast/Slime/Animations/Default/Idle.blockyanim" }
]
},
"Death": {
"Animations": [
{
"Animation": "NPC/Beast/Slime/Animations/Default/Death.blockyanim",
"Loop": false
}
]
},
"Walk_Backward": {
"Animations": [
{ "Animation": "NPC/Beast/Slime/Animations/Default/Walk_Backward.blockyanim" }
]
},
"Run": {
"Animations": [
{ "Animation": "NPC/Beast/Slime/Animations/Default/Run.blockyanim" }
]
},
"Crouch": {
"Animations": [
{ "Animation": "NPC/Beast/Slime/Animations/Default/Crouch.blockyanim" }
]
},
"Crouch_Walk": {
"Animations": [
{ "Animation": "NPC/Beast/Slime/Animations/Default/Crouch_Walk.blockyanim" }
]
},
"Crouch_Walk_Backward": {
"Animations": [
{ "Animation": "NPC/Beast/Slime/Animations/Default/Crouch_Walk_Backward.blockyanim" }
]
}
},
"Icon": "Icons/ModelsGenerated/Slime.png",
"IconProperties": {
"Scale": 0.25,
"Rotation": [0, -45, 0],
"Translation": [0, -61]
}
}

Campos del Modelo de Servidor

CampoTipoPropósito
ModelStringRuta al archivo .blockymodel (relativa a Common/)
TextureStringRuta a la textura .png (relativa a Common/)
EyeHeightNumberPosición vertical de los ojos del NPC en bloques — afecta la cámara y la línea de visión
CrouchOffsetNumberCuánto baja el modelo al agacharse
HitBoxObjectCaja de colisión para detección de daño. Min/Max definen las esquinas en bloques
CameraObjectCómo la cabeza del NPC sigue a los objetivos. TargetNodes debe coincidir con los nombres de grupo en el modelo
AnimationSetsObjectMapea estados del juego a archivos de animación. Cada conjunto puede tener múltiples animaciones con pesos
IconStringRuta del icono del menú de aparición (relativa a Common/)
IconPropertiesObjectEscala, rotación y traslación para el renderizado del icono

Paso 5: Definir el Rol de NPC

El Rol de NPC define el comportamiento y las estadísticas. En lugar de escribir la IA desde cero, Hytale usa herencia de plantillas — eliges una plantilla de comportamiento y solo sobrescribes lo que difiere.

Crea Server/NPC/Roles/Slime.json:

{
"Type": "Variant",
"Reference": "Template_Predator",
"Modify": {
"Appearance": "Slime",
"MaxHealth": 75,
"KnockbackScale": 0.5,
"IsMemory": true,
"MemoriesCategory": "Beast",
"NameTranslationKey": {
"Compute": "NameTranslationKey"
}
},
"Parameters": {
"NameTranslationKey": {
"Value": "server.npcRoles.Slime.name",
"Description": "Translation key for NPC name display"
}
}
}

Cómo Funciona la Herencia de Plantillas

El patrón "Type": "Variant" + "Reference": "Template_Predator" significa:

  1. Comenzar con todos los campos de Template_Predator (IA hostil, lógica de persecución, patrones de ataque, rango de visión)
  2. Sobrescribir solo los campos listados en "Modify" (apariencia, salud, retroceso, etc.)
  3. Todo lo demás (toma de decisiones, lógica de combate, velocidades de movimiento) viene de la plantilla

Plantillas de NPC Disponibles

PlantillaComportamientoUsar Para
Template_PredatorHostil — persigue y ataca jugadores en cuanto los veEnemigos, criaturas hostiles
Template_PreyPasivo — huye cuando se siente amenazadoConejos, ciervos, animales pequeños
Template_NeutralNeutral — ataca solo cuando es provocadoOsos, lobos
Template_DomesticDoméstico — sigue al dueño, puede ser encerrado en corralesAnimales de granja, mascotas
Template_Beasts_Passive_CritterCriatura pasiva — deambula, huyeArdillas, ranas, insectos

Campos del Rol de NPC

CampoTipoPropósito
AppearanceStringDebe coincidir con el nombre del archivo del Modelo de Servidor (sin .json). Así es como el motor vincula el Rol con el Modelo
MaxHealthNumberPuntos de vida. Los enemigos del juego base van desde 30 (Esqueleto) hasta 500+ (jefes)
KnockbackScaleNumberResistencia al retroceso. 1.0 = normal, 0.5 = mitad de retroceso, 0 = inamovible
IsMemoryBooleanSi el NPC aparece en el bestiario de Memorias del jugador
MemoriesCategoryStringPestaña del bestiario: Critter, Beast, Boss, Other
NameTranslationKeyComputeClave de traducción para el nombre que se muestra sobre la cabeza del NPC

El Patrón Compute

"NameTranslationKey": {
"Compute": "NameTranslationKey"
}

Esto le dice al motor: “obtener el valor de NameTranslationKey del bloque Parameters.” La sección Parameters luego proporciona el valor real:

"Parameters": {
"NameTranslationKey": {
"Value": "server.npcRoles.Slime.name",
"Description": "Translation key for NPC name display"
}
}

Esta indirección existe porque las plantillas usan Compute para leer valores que cada variante define de manera diferente. Cada variante proporciona su propio valor de NameTranslationKey, pero la lógica de la plantilla para usarlo permanece igual.


Paso 6: Crear la Tabla de Botín

La tabla de botín controla qué loot se suelta cuando el NPC muere. Por ahora, crea una tabla de drops vacía para que el Slime no suelte nada:

Crea Server/Drops/Drop_Slime.json:

{}

Luego conéctala al Slime agregando DropList al Rol de NPC. Abre Server/NPC/Roles/Slime.json y agrega la línea resaltada:

{
"Type": "Variant",
"Reference": "Template_Predator",
"Modify": {
"Appearance": "Slime",
"MaxHealth": 75,
"DropList": "Drop_Slime",
"KnockbackScale": 0.5,
"IsMemory": true,
"MemoriesCategory": "Beast",
"NameTranslationKey": {
"Compute": "NameTranslationKey"
}
},
"Parameters": {
"NameTranslationKey": {
"Value": "server.npcRoles.Slime.name",
"Description": "Translation key for NPC name display"
}
}
}

El "DropList": "Drop_Slime" indica al motor que busque Server/Drops/Drop_Slime.json cuando el NPC muera.


Paso 7: Añadir Traducciones

Crea un archivo server.lang para cada idioma bajo Server/Languages/:

Server/Languages/en-US/server.lang

npcRoles.Slime.name = Slime

Server/Languages/es/server.lang

npcRoles.Slime.name = Slime

Server/Languages/pt-BR/server.lang

npcRoles.Slime.name = Slime

La clave de traducción en el archivo .lang debe coincidir con el Parameters.NameTranslationKey.Value en el Rol de NPC — pero sin el prefijo server.. El motor añade el prefijo automáticamente al resolver archivos de idioma del servidor.


Paso 8: Empaquetar y Probar

  1. Copia la carpeta CreateACustomNPC/ a %APPDATA%/Hytale/UserData/Mods/

  2. Inicia Hytale y entra en el Modo Creativo

  3. Revisa el registro en %APPDATA%/Hytale/UserData/Logs/ para confirmar que tu mod se cargó:

    [Hytale] Loading assets from: ...\Mods\CreateACustomNPC\Server
    [AssetRegistryLoader] Loading assets from ...\Mods\CreateACustomNPC\Server
  4. Otórgate permisos de operador y genera el Slime usando comandos de chat:

    /op self
    /npc spawn Slime
  5. Verifica:

Slime invocado en el juego de noche, brillando en verde con la Espada de Cristal equipada

  • El modelo se renderiza correctamente con la textura del slime
  • El NPC es hostil y te persigue en cuanto te ve
  • Las animaciones de ataque, caminar, correr y muerte se reproducen correctamente
  • El nombre “Slime” aparece sobre su cabeza
  • Al matarlo suelta uno de: Mineral de Cristal de Slime (50%), Poción de Salud (30%), o nada (20%)

Errores Comunes

ProblemaCausaSolución
Common Asset 'path' must be within the rootLa ruta del modelo/textura no comienza con NPC/, Icons/, etc.Mueve los archivos bajo un directorio raíz permitido en Common/
Common Asset 'path' doesn't existLa ruta en el JSON no coincide con la ubicación real del archivoVerifica cada ruta en el Modelo de Servidor — son relativas a Common/
El NPC aparece pero es invisibleLa ruta Model del Modelo de Servidor es incorrecta o el .blockymodel está corruptoRe-exporta desde Blockbench, verifica la ruta
El NPC se queda quieto, no atacaPlantilla incorrecta o animaciones faltantesVerifica que Reference sea Template_Predator y que los 9 conjuntos de animación existan
El NPC se desliza sin animaciónEl nombre del conjunto de animación no coincide con el nombre esperadoUsa los nombres exactos: Walk, Run, Idle, Attack, Death, etc.
El nombre no aparece sobre el NPCDiscrepancia en la clave de traducciónAsegúrate de que la clave en .lang coincida con Parameters.NameTranslationKey.Value menos el prefijo server.
La animación de muerte se repite en bucleFalta "Loop": false en la animación de MuerteAñade "Loop": false a la entrada de Death en AnimationSets
La tabla de botín no funcionaFalta el campo DropList en el Rol de NPCAñade "DropList": "Drop_Slime" al bloque Modify (omitido aquí ya que Template_Predator lo maneja)

Siguientes Pasos