1. Crear y asignar un script
Cada proyecto tiene una carpeta scripts. Puedes crear, editar, renombrar y eliminar scripts desde
la pestana Scripts del panel inferior. Cada objeto puede tener un script asignado
desde el Inspector. Un mismo script puede asignarse a varios objetos.
Usa Refresh, situado a la derecha de la pestaña Scripts, después de crear, eliminar o cambiar el nombre de un archivo directamente desde VS Code o el Explorador. Si utilizas Rename desde el editor, GameCrom cambia el archivo y actualiza automáticamente sus asignaciones en los objetos, escenas guardadas y prefabs.
- Selecciona un objeto en la escena o en la jerarquia.
- En el Inspector busca el componente Script o abre la pestana Scripts.
- Pulsa Create para crear uno nuevo o elige uno existente en File.
- Pulsa Edit para abrirlo en Visual Studio Code.
- Despues de guardar cambios en el archivo, pulsa Update en el Inspector para volver a leer el script y actualizar sus propiedades publicas.
- Pulsa Play para ejecutar el script.
Los scripts solo se ejecutan en Play. Al salir de Play, la escena vuelve al estado de edicion.
Módulos e imports entre scripts
Los scripts pueden dividirse en varios archivos usando módulos JavaScript con import y export. Las rutas relativas se resuelven desde la carpeta del script que realiza el import y funcionan tanto en Play como en los juegos publicados en GameCrom.
// Gameplay.js
import { LEVELS } from "./Levels.js";
export function start(object) {
debug(LEVELS[1]);
}
// Levels.js
export const LEVELS = {
1: { words: ["CASA", "MESA", "LIBRO"] }
};
Mantén los módulos dentro de scripts/. Detén y vuelve a iniciar Play después de modificar una dependencia importada para recargar todos los módulos.
En Play > Options, activa Hide panels in Play para ocultar los paneles laterales e inferior mientras pruebas el juego. La barra superior y Stop permanecen accesibles; al salir de Play se restaura la disposicion anterior.
En el mismo menú puedes activar Fullscreen, silenciar el juego con Mute in Play, ajustar el Volume general solo para Play y las preescuchas del editor (no cambia las compilaciones), o elegir la escala Original, Fit o Fill. En la cámara, Viewport ofrece 800 × 600, 1280 × 720, 1920 × 1080, 720 × 1280, 1080 × 1920 y tamaño personalizado.
Seleccionar objetos en la escena
Haz clic sobre un objeto para seleccionarlo y editarlo en el Inspector. Cuando varios objetos se superponen, los clics consecutivos rápidos en el mismo punto alternan entre ellos.
Si pasan 1,5 segundos o más desde el último clic, el siguiente clic sobre el objeto seleccionado mantiene su selección, aunque haya otro objeto delante o detrás. Esto permite retomar su edición sin cambiar de objeto accidentalmente. Un nuevo clic rápido en el mismo punto vuelve a alternar entre los objetos superpuestos. Si haces clic en una zona donde el objeto seleccionado no está presente, se selecciona el objeto de esa zona.
Prefabs
Un prefab es una plantilla reutilizable de un objeto. Sirve para guardar un objeto de la escena con sus propiedades y sus hijos, y despues crear copias nuevas cuando las necesites.
- Selecciona el objeto que quieres convertir en prefab.
- Abre la pestana Prefabs en el panel inferior.
- Pulsa Create From Selection.
- Escribe el nombre del prefab y confirma.
- Usa Instantiate para crear una copia del prefab en la escena.
- Usa Delete para eliminar el archivo del prefab del proyecto.
La lista de prefabs muestra una miniatura del objeto raiz. Si el objeto tiene textura se ve la imagen; si no, se muestra una forma con su color.
En la barra superior del editor, Snap conserva el desplazamiento por pasos. El check Snap to Grid encaja la esquina superior izquierda del objeto directamente en la rejilla.
Los prefabs se guardan dentro de la carpeta prefabs del proyecto. Al instanciar uno, el
motor crea objetos nuevos con IDs nuevos para no modificar el prefab original ni pisar objetos de la
escena.
| Se guarda | Detalle |
|---|---|
| Objeto raiz | Nombre, tag, posicion, escala, rotacion, color, textura, colision, visibilidad y Static. |
| Hijos | La jerarquia completa que cuelga del objeto seleccionado. |
| Script | La referencia al script asignado al objeto. |
| Animacion | La animacion asignada y sus opciones de reproduccion. |
| Particulas | El sistema de particulas asignado y sus opciones. |
| Componentes | Componentes anadidos al objeto, como Audio Source, Parallax o Character Controller. |
Editar la plantilla
El objeto convertido en prefab y las copias creadas con Instantiate quedan vinculados. Haz doble clic sobre el prefab en la lista o pulsa Open para abrir Prefab Mode. Allí puedes seleccionar el objeto raíz o cualquiera de sus hijos en la jerarquía y editar sus propiedades y componentes en el Inspector. Pulsa Save Prefab para guardar la plantilla y actualizar las instancias vinculadas, o Back to Scene para volver. Si hay cambios sin guardar, el editor pide confirmación antes de descartarlos. El modo Prefab no permite iniciar Play ni cambiar de escena.
Editar una instancia en la escena
Selecciona una instancia vinculada en la escena o en la jerarquía. Debajo de GameObject, el Inspector muestra el bloque Prefab Instance y el número de cambios locales. El rombo en la jerarquía distingue los objetos vinculados; se rellena cuando tienen cambios locales.
- Open Prefab: abre la plantilla para editarla directamente.
- Apply to Prefab: guarda las propiedades y componentes de esta instancia en la plantilla y actualiza las demás instancias vinculadas. Conserva la posición de cada instancia y sus cambios locales cuando no se han aplicado.
- Revert: descarta los cambios locales de esta instancia y recupera los valores de la plantilla, sin mover su posición en la escena.
- Unpack: desvincula esta instancia y sus hijos. Seguirán en la escena como objetos independientes.
Guarda la escena después de crear, vincular, aplicar, revertir o desvincular una instancia para conservar esos cambios.
Vincular una copia antigua
Para vincular una copia independiente, selecciona su objeto raíz, busca el bloque Prefab en el Inspector, elige la plantilla y pulsa Link selected copy. Si coincide con el prefab, aparecerán Apply to Prefab, Revert y Unpack. El vínculo mantiene las propiedades actuales de la copia.
Luces 2D
Puedes crear un objeto Light desde Add GameObject. En Play no se dibuja como sprite normal: ilumina la escena con una luz radial sobre el canvas. Los objetos Light no muestran Sprite Renderer ni Collider 2D porque no son objetos fisicos ni sprites del juego. La luz solo afecta a las capas que estan por debajo de ella en el orden de dibujo; los objetos colocados por encima se dibujan despues y no quedan iluminados por esa luz.
| Propiedad | Uso |
|---|---|
Enabled | Activa o desactiva la luz. |
Light Color | Color de la luz. |
Radius | Alcance de la luz en pixeles de mundo. |
Intensity | Fuerza de la luz, de 0 a 1. |
Opacity | Transparencia global de la luz, de 0 a 1. |
Softness | Suavizado del borde, de 0 a 1. |
Effect | Animacion de luz: None, Torch, Candle, Alarm, Fluorescent o Pulse. |
Effect Speed | Velocidad del efecto. 0 deja la luz practicamente fija. |
Effect Amount | Cantidad de variacion de intensidad del efecto. |
Radius Amount | Cantidad de variacion del radio durante el efecto. |
Effect Color | Color secundario usado por efectos como Alarm y Pulse. |
Los efectos se animan durante Play. Torch y Candle simulan parpadeo organico, Alarm alterna hacia un color secundario, Fluorescent crea pequenos cortes de intensidad y Pulse respira suavemente. El boton Play del componente permite previsualizar el efecto en el editor sin ejecutar el juego.
Sprite Studio
Sprite Studio une el dibujo y la animación en una sola vista, sin sustituir las pestañas Sprites y Animations. El selector Canvas de ambas herramientas ofrece 16 × 16, 32 × 32, 64 × 64, 32 × 16, 64 × 32 y 64 × 16. En Sprites crea un lienzo nuevo; en Sprite Studio cambia todos los fotogramas conservando los píxeles que caben y avisa si el nuevo tamaño recorta dibujos. Dibuja en el lienzo, usa Add blank o Duplicate para crear fotogramas y observa el resultado al instante en Live preview. Puedes reordenar o quitar fotogramas, ajustar los FPS y el bucle, pausar la vista previa y activar Onion skin para ver los fotogramas vecinos mientras dibujas.
Open clip carga una animación de sprites existente para editarla. Save Animation crea los PNG necesarios en Textures y crea o actualiza el clip de Animations: son los mismos recursos que utiliza el juego publicado en GameCrom. Los PNG originales de un clip importado no se sobrescriben. Hasta guardar, el dibujo permanece como borrador en memoria; cambiar de pestaña conserva el borrador, pero cerrar el editor no lo guarda.
En Tracing reference, usa Load image para elegir cualquier imagen como guía, aunque tenga otra resolución. Selecciona la herramienta Reference: arrastra dentro de la imagen para moverla y usa los ocho tiradores amarillos para ajustar su ancho y alto al marco de píxeles. Opacity controla su transparencia. La referencia y sus tiradores solo se ven en el lienzo de edición; no aparecen en la vista previa ni en los PNG exportados.
Recortar sprites
El recortador sirve para separar una textura grande que contiene muchos sprites mezclados, como una hoja de sprites. Los recortes se guardan como texturas PNG nuevas dentro del proyecto.
- Abre la pestana Slice Sprite del panel inferior.
- Elige la textura fuente.
- Al abrir una imagen nueva no aparece una cuadrícula completa. Usa Add Rect para un recorte manual, Grid para una cuadrícula regular o Auto Slice para detectar regiones separadas por transparencia.
- Configura Cell W y Cell H con el tamano de cada sprite.
- Ajusta Offset X/Y si la hoja tiene margen exterior.
- Haz clic en una casilla para seleccionarla. Arrástrala para moverla o usa sus seis tiradores amarillos para cambiar su tamaño sin modificar las demás.
- Mantén Shift y arrastra para mover toda la cuadrícula. Usa la rueda del ratón sobre la imagen para ampliar o reducir la vista.
- Mantén pulsado el botón derecho y arrastra para desplazar la vista (pan).
- Los botones de la selección permiten excluir/incluir una casilla o devolverla a su posición y tamaño originales.
- Ajusta Spacing X/Y si hay separacion entre sprites.
- Usa Columns y Rows para limitar el area, o deja
0para calcularlo automaticamente. - Pulsa Save Slices para guardar cada recorte como textura nueva.
- Pulsa Save Pattern para conservar el trabajo de esta imagen dentro del proyecto; Revert restaura el último patrón guardado.
Las casillas ajustadas manualmente mantienen su posición y tamaño aunque cambies los valores generales de la cuadrícula. Auto Slice necesita fondo transparente y sus resultados pueden corregirse a mano antes de guardar. La textura original no se modifica. Si Empty esta desactivado, los recortes totalmente transparentes se saltan.
2. Ciclo de ejecucion
Un script puede exportar funciones de ciclo. Todas reciben el objeto que tiene asignado el script. Si no declaras una funcion, simplemente no se llama.
| Funcion | Cuando se llama | Parametros |
|---|---|---|
start(object) | Una vez al entrar en Play. | object: objeto dueño del script. |
fixedUpdate(object, fixedDeltaTime) | A paso fijo, 60 veces por segundo si el rendimiento lo permite. | Movimiento estable, fisica y empujes. |
update(object, deltaTime) | Cada frame durante Play. | Input, logica normal, movimiento visual y UI. |
lateUpdate(object, deltaTime) | Al final del frame, despues de update y colisiones. | Camara, UI dependiente de posiciones finales y ajustes finales. |
export function start(object) {
debug("Empieza: " + object.name);
}
export function fixedUpdate(object, fixedDeltaTime) {
// Paso fijo: ideal para fisica.
}
export function update(object, deltaTime) {
object.x += 100 * deltaTime;
}
export function lateUpdate(object, deltaTime) {
// Se ejecuta cuando todos los update del frame han terminado.
}
3. El objeto recibido
El parametro object es el objeto real de la escena durante Play. Puedes leer sus datos y
cambiar propiedades como posicion, rotacion, escala, color, opacidad o estado activo.
export function start(object) {
debug({
id: object.id,
name: object.name,
tag: object.tag,
x: object.x,
y: object.y
});
}
Si quieres ver todo lo que tiene un objeto, puedes enviarlo completo a la consola:
export function start(object) {
debug(object);
}
4. Manejo de variables
En los scripts puedes crear variables normales de JavaScript. Segun donde las guardes, duran solo dentro de una funcion, pertenecen a un objeto, a la escena actual o a toda la partida del proyecto.
Si quieres que cada objeto tenga un valor configurable desde el Inspector, exporta
properties. Es la opcion adecuada para velocidades, colores, modos y referencias a
objetos o assets. Cada instancia conserva sus propios valores; una variable declarada fuera de las
funciones del script, en cambio, se comparte entre todos los objetos que usan ese script.
Tipos habituales
| Tipo | Ejemplo | Uso |
|---|---|---|
| number | let vida = 100; | Numeros, velocidad, tiempo, puntuacion. |
| string | let estado = "idle"; | Texto, nombres, estados. |
| boolean | let vivo = true; | Valores verdadero/falso. |
| object | let datos = { vida: 100 }; | Agrupar datos. |
| array | let inventario = []; | Listas de valores. |
Variables locales
Viven solo dentro de la funcion donde se crean. Se pierden al terminar esa llamada.
export function update(object, deltaTime) {
const speed = 120;
object.translate(speed * deltaTime, 0);
}
Variables del script
Si las creas fuera de start y update, se conservan mientras ese script esta
cargado en Play. Si el mismo script se asigna a varios objetos, esa variable se comparte entre ellos.
let totalUpdates = 0;
export function update(object, deltaTime) {
totalUpdates += 1;
debug(totalUpdates);
}
Variables locales de un objeto
Para guardar datos de un objeto concreto, crea tus propias propiedades dentro de object.
Cada objeto tendra sus propios valores.
export function start(object) {
object.vida = 100;
object.velocidad = 180;
}
export function update(object, deltaTime) {
object.translate(object.velocidad * deltaTime, 0);
}
Variables globales de escena
Usa Scene.vars para datos compartidos por todos los scripts de la escena actual. Se reinicia
al entrar en Play y tambien cuando cargas otra escena con Scene.load.
export function start(object) {
Scene.vars.enemigos = Scene.vars.enemigos || 0;
Scene.vars.enemigos += 1;
}
Variables globales de proyecto
Usa Project.vars para datos que deben sobrevivir al cambiar de escena durante la misma
partida, como puntuacion, vidas o progreso.
export function start(object) {
Project.vars.score = Project.vars.score || 0;
}
export function update(object, deltaTime) {
Project.vars.score += 1;
debug("Score: " + Project.vars.score);
}
Datos guardados con PlayerPrefs
Usa PlayerPrefs para guardar datos que deben seguir existiendo aunque cierres el juego,
como récord, opciones, volumen, monedas o el último nivel desbloqueado. Los datos se guardan
separados por proyecto.
Project.vars se borra al salir de Play. PlayerPrefs siempre guarda inmediatamente en local. Si el jugador inicia sesión en GameCrom, GameCrom sincroniza automáticamente los cambios con la nube cada dos minutos y al salir del juego. Las escrituras se agrupan y solo se envía el último valor pendiente de cada clave. PlayerPrefs.save() se mantiene por compatibilidad, pero no fuerza llamadas a la nube.
| Funcion | Uso | Ejemplo |
|---|---|---|
PlayerPrefs.setString(key, value) | Guarda texto. | PlayerPrefs.setString("playerName", "Alex") |
PlayerPrefs.getString(key, defaultValue) | Lee texto. | PlayerPrefs.getString("playerName", "Player") |
PlayerPrefs.setNumber(key, value) | Guarda un numero. | PlayerPrefs.setNumber("volume", 0.8) |
PlayerPrefs.getNumber(key, defaultValue) | Lee un numero. | PlayerPrefs.getNumber("volume", 1) |
PlayerPrefs.setInt(key, value) | Guarda un entero. | PlayerPrefs.setInt("coins", 25) |
PlayerPrefs.getInt(key, defaultValue) | Lee un entero. | PlayerPrefs.getInt("coins", 0) |
PlayerPrefs.setBool(key, value) | Guarda verdadero/falso. | PlayerPrefs.setBool("music", true) |
PlayerPrefs.getBool(key, defaultValue) | Lee verdadero/falso. | PlayerPrefs.getBool("music", true) |
PlayerPrefs.setJSON(key, value) | Guarda objetos o arrays. | PlayerPrefs.setJSON("inventory", ["key"]) |
PlayerPrefs.getJSON(key, defaultValue) | Lee objetos o arrays. | PlayerPrefs.getJSON("inventory", []) |
PlayerPrefs.hasKey(key) | Comprueba si existe una clave. | PlayerPrefs.hasKey("record") |
PlayerPrefs.deleteKey(key) | Borra una clave. | PlayerPrefs.deleteKey("record") |
PlayerPrefs.deleteAll() | Borra todos los datos guardados del proyecto actual. | PlayerPrefs.deleteAll() |
PlayerPrefs.keys() | Devuelve las claves guardadas del proyecto actual. | PlayerPrefs.keys() |
PlayerPrefs.save() | Existe por compatibilidad. En este motor el guardado es inmediato. | PlayerPrefs.save() |
Ejemplo: guardar record
export function start(object) {
Project.vars.score = 0;
Project.vars.record = PlayerPrefs.getInt("record", 0);
}
export function update(object, deltaTime) {
Project.vars.score += Math.round(10 * deltaTime);
if (Project.vars.score > Project.vars.record) {
Project.vars.record = Project.vars.score;
PlayerPrefs.setInt("record", Project.vars.record);
}
debug({
score: Project.vars.score,
record: Project.vars.record
});
}
Ejemplo: guardar opciones
export function start(object) {
const volume = PlayerPrefs.getNumber("volume", 1);
const fullscreen = PlayerPrefs.getBool("fullscreen", false);
debug({ volume, fullscreen });
}
export function update(object) {
if (Input.getKeyDown("M")) {
PlayerPrefs.setNumber("volume", 0);
}
if (Input.getKeyDown("F")) {
const current = PlayerPrefs.getBool("fullscreen", false);
PlayerPrefs.setBool("fullscreen", !current);
}
}
Matematicas disponibles
Los scripts pueden usar directamente el objeto estandar Math de JavaScript. El motor
tambien incluye las APIs Random, Mathf y Vector2.
| Operacion actual | Ejemplo |
|---|---|
| Minimo, maximo y valor absoluto | Math.min(a, b), Math.max(a, b), Math.abs(x) |
| Redondeo | Math.floor(x), Math.ceil(x), Math.round(x) |
| Potencias y raiz | Math.pow(x, 2), Math.sqrt(x) |
| Distancia 2D | Math.hypot(dx, dy) |
| Angulos y trigonometria | Math.atan2(y, x), Math.sin(x), Math.cos(x) |
| Signo | Math.sign(x) |
| Aleatorio entre 0 y 1 | Math.random() |
const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
const lerp = (a, b, t) => a + (b - a) * t;
const randomRange = (min, max) => min + Math.random() * (max - min);
API Random
| Funcion | Uso | Ejemplo |
|---|---|---|
Random.value() | Decimal entre 0 incluido y 1 excluido. | Random.value() |
Random.range(min, max) | Decimal entre los dos valores. | Random.range(10, 20) |
Random.int(min, max) | Entero entre min y max, incluyendo ambos. | Random.int(1, 6) |
Random.choose(array) | Elemento aleatorio o null si el array esta vacio. | Random.choose(["red", "blue"]) |
Random.chance(probability) | Devuelve true con una probabilidad entre 0 y 1. | Random.chance(0.25) |
Random.sign() | Devuelve aleatoriamente -1 o 1. | Random.sign() |
Random.shuffle(array) | Devuelve una copia mezclada sin modificar el array original. | Random.shuffle(cards) |
export function start(object) {
object.x = Random.range(100, 700);
object.vida = Random.int(2, 5);
object.color = Random.choose(["#ff0000", "#00ff00", "#0088ff"]);
if (Random.chance(0.2)) {
debug("Enemigo especial");
}
}
Mathf trabaja con numeros y angulos. Vector2 devuelve objetos nuevos
{ x, y }; no modifica los vectores recibidos.
API Mathf
Mathf.clamp(value, min, max) | Limita un valor. |
Mathf.clamp01(value) | Limita entre 0 y 1. |
Mathf.lerp(a, b, t) | Interpola usando t entre 0 y 1. |
Mathf.inverseLerp(a, b, value) | Calcula la proporcion de value entre a y b. |
Mathf.moveTowards(current, target, step) | Acerca un numero sin sobrepasarlo. |
Mathf.repeat(value, length) | Repite un valor dentro de un intervalo. |
Mathf.pingPong(value, length) | Oscila entre 0 y length. |
Mathf.degToRad(degrees), radToDeg(radians) | Convierte angulos. |
Mathf.deltaAngle(a, b) | Menor diferencia angular con signo. |
Mathf.lerpAngle(a, b, t) | Interpola por el camino angular mas corto. |
API Vector2
Vector2.create(x, y) | Crea un vector. |
Vector2.add(a, b), subtract(a, b) | Suma o resta. |
Vector2.multiply(v, scalar), divide(v, scalar) | Escala un vector. |
Vector2.length(v) | Longitud. |
Vector2.distance(a, b) | Distancia entre puntos. |
Vector2.normalize(v) | Vector de longitud 1. |
Vector2.dot(a, b) | Producto escalar. |
Vector2.angle(a, b) | Angulo en grados. |
Vector2.lerp(a, b, t) | Interpola dos vectores. |
Vector2.moveTowards(a, b, distance) | Acerca un punto a otro. |
const direction = Vector2.normalize({
x: enemy.x - object.x,
y: enemy.y - object.y
});
object.translate(direction.x * 120 * deltaTime, direction.y * 120 * deltaTime);
5. Movimiento de objetos
Durante Play los objetos tienen metodos utiles para moverse y orientarse. Estos metodos devuelven el propio objeto, asi que puedes encadenarlos si te resulta comodo.
| Metodo | Uso | Ejemplo |
|---|---|---|
object.translate(x, y) | Mueve el objeto en sus coordenadas locales. | player.translate(10, 0) |
object.lookAt(target, eje) | Rota el objeto mirando a otro objeto o punto usando el eje indicado. | player.lookAt(enemy, "x") |
object.moveTowards(target, speed, deltaTime) | Mueve el objeto hacia un objetivo. | player.moveTowards(target, 150, deltaTime) |
export function update(object, deltaTime) {
object.translate(100 * deltaTime, 0);
}
export function update(object, deltaTime) {
const enemy = FindByTag("Enemy");
if (!enemy) return;
object.lookAt(enemy, "x");
object.moveTowards(enemy, 120, deltaTime);
}
lookAt y moveTowards aceptan un objeto o un punto como { x: 100, y: 50 }.
En lookAt, el eje por defecto es "x". Tambien puedes usar "-x",
"y" o "-y". Por ejemplo, si tu sprite mira hacia arriba, usa
object.lookAt(enemy, "-y").
6. Jerarquia de objetos
Durante Play puedes consultar y cambiar relaciones padre/hijo. Al cambiar de padre, el motor intenta mantener la posicion visual del objeto en el mundo.
| Metodo | Uso | Ejemplo |
|---|---|---|
object.addChild(child) | Hace que otro objeto sea hijo de este objeto. | player.addChild(gun) |
object.removeChild(child) | Quita un hijo directo y lo deja sin padre. | player.removeChild(gun) |
object.parent() | Devuelve el padre del objeto o null. | const p = gun.parent() |
object.root() | Devuelve el objeto raiz de la jerarquia. | const root = gun.root() |
object.children() | Devuelve un array con los hijos directos. | const hijos = player.children() |
object.destroyAllChildren(tiempo) | Destruye todos los hijos directos, al momento o tras un tiempo. | player.destroyAllChildren(1) |
export function start(object) {
const gun = FindByName("Gun");
if (!gun) return;
object.addChild(gun);
}
export function update(object, deltaTime) {
for (const child of object.children()) {
debug(child.name);
}
}
export function start(object) {
object.destroyAllChildren(2);
}
addChild no permite crear bucles de jerarquia. Por ejemplo, no puedes hacer hijo a un
objeto de uno de sus propios descendientes.
7. Propiedades del objeto
Estas son las propiedades principales que puedes leer y modificar desde un script.
| Propiedad | Tipo | Uso | Ejemplo |
|---|---|---|---|
id | string/number | Identificador unico del objeto. | debug(object.id) |
name | string | Nombre visible en el editor. | object.name = "Player" |
tag | string | Etiqueta para buscar objetos por categoria. | object.tag = "Enemy" |
parentId | string/null | ID del padre en la jerarquia. | debug(object.parentId) |
type | string | Tipo visual: square o circle. | debug(object.type) |
active | boolean | Activa o desactiva el objeto. | object.active = false |
isStatic | boolean | Marca el objeto como estatico para optimizaciones futuras. | object.isStatic = true |
visibleInPlay | boolean | Controla si se ve durante Play. | object.visibleInPlay = true |
x, y | number | Posicion local del objeto. | object.x += 10 |
w, h | number | Tamano base del objeto. | object.w = 80 |
rotation | number | Rotacion en grados. | object.rotation += 90 * deltaTime |
scaleX, scaleY | number | Escala horizontal y vertical. | object.scaleX = 2 |
z | number | Capa de orden visual. | object.z = 5 |
color | string | Color en formato hexadecimal. | object.color = "#ff0000" |
opacity | number | Opacidad entre 0 y 1. | object.opacity = 0.5 |
texture | string | Nombre de la textura asignada. | object.texture = "player.png" |
textureTilingX, textureTilingY | number | Repeticion de la textura. | object.textureTilingX = 2 |
textureOffsetX, textureOffsetY | number | Desplazamiento de la textura. | object.textureOffsetX += deltaTime |
textureFlipX, textureFlipY | boolean | Voltea la textura. | object.textureFlipX = true |
pixelPerfect | boolean | Render de textura con aspecto pixel art. | object.pixelPerfect = true |
animation | string | ID de animacion asignada. | debug(object.animation) |
animationPlaying | boolean | Activa o pausa la animacion. | object.animationPlaying = true |
animationRunInPlay | boolean | Indica si la animacion arranca en Play. | object.animationRunInPlay = true |
particleSystem | string | ID del sistema de particulas asignado. | debug(object.particleSystem) |
particlesPlaying | boolean | Activa o pausa particulas. | object.particlesPlaying = true |
particlesRunInPlay | boolean | Indica si las particulas arrancan en Play. | object.particlesRunInPlay = true |
particlesDetached | boolean | Permite que la estela de particulas quede separada del objeto. | object.particlesDetached = true |
collisionEnabled | boolean | Marca el collider como activo. | object.collisionEnabled = true |
isTrigger | boolean | Marca el collider como trigger. | object.isTrigger = true |
collider | object | Datos del collider: shape, offsetX/Y, width/height y radius. | object.collider.shape = "capsule" |
script | string | Nombre del script asignado. | debug(object.script) |
scriptProperties | object | Valores expuestos propios de esta instancia. | object.scriptProperties.speed |
Propiedades publicas de un script
Exporta un objeto properties para mostrar campos editables debajo del script en el Inspector. Los valores se guardan por objeto y se conservan en escenas, prefabs y clones.
Tipos disponibles en el Inspector
| Tipo | Control del Inspector | Como se asigna | Ejemplo |
|---|---|---|---|
number | Campo numerico | Escribe el valor. Puedes limitarlo con min, max y step. | speed: { type: "number", default: 100, min: 0, max: 500, step: 5 } |
boolean | Casilla de verificacion | Marca o desmarca la casilla. | enabled: { type: "boolean", default: true } |
string | Campo de texto | Escribe el texto directamente. | message: { type: "string", default: "Hello" } |
color | Selector de color | Elige un color en el selector. | tint: { type: "color", default: "#ffffff" } |
select | Lista desplegable | Elige uno de los valores definidos en options. | mode: { type: "select", default: "slow", options: ["slow", "fast"] } |
object | Buscador y lista de objetos de la escena | Busca por nombre y selecciona un objeto en la lista filtrada. La propiedad guarda su ID. | target: { type: "object", default: "" } |
texture | Lista de texturas | Selecciona una textura importada en el proyecto. | texture: { type: "texture", default: "" } |
sound | Lista de sonidos | Selecciona un sonido importado en el proyecto. | sound: { type: "sound", default: "" } |
animation | Lista de animaciones | Selecciona un clip de animacion del proyecto. La propiedad guarda su ID. | animation: { type: "animation", default: "" } |
prefab | Lista de prefabs | Selecciona un prefab del proyecto. La propiedad guarda su nombre. | enemyPrefab: { type: "prefab", default: "" } |
Asigna primero el script al objeto. Sus campos apareceran debajo del selector de script en el Inspector. Los selectores de assets solo muestran recursos que ya existen en las pestañas correspondientes del proyecto.
Numeros, interruptores, texto, color y listas
export const properties = {
speed: { type: "number", label: "Speed", default: 100, min: 0, max: 500, step: 5 },
enabled: { type: "boolean", default: true },
message: { type: "string", label: "Message", default: "Hello" },
tint: { type: "color", default: "#ffffff" },
mode: {
type: "select",
label: "Movement",
default: "slow",
options: [
{ value: "slow", label: "Slow" },
{ value: "fast", label: "Fast" }
]
}
};
export function update(object, deltaTime, properties) {
if (!properties.enabled) return;
const multiplier = properties.mode === "fast" ? 2 : 1;
object.translate(-properties.speed * multiplier * deltaTime, 0);
}
Enlazar e instanciar un prefab
El tipo prefab muestra los prefabs del proyecto en un desplegable. El valor recibido es el nombre del prefab seleccionado.
export const properties = {
enemyPrefab: { type: "prefab", label: "Enemy prefab", default: "" },
spawnOffsetX: { type: "number", label: "Spawn offset X", default: 64 }
};
export async function start(object, properties) {
if (!properties.enemyPrefab) return;
const enemy = await Prefab.instantiate(properties.enemyPrefab, {
x: object.x + properties.spawnOffsetX,
y: object.y
});
if (enemy) debug("Created: " + enemy.name);
}
Enlazar un objeto de la escena
El tipo object permite elegir otro objeto de la escena y guarda su ID. Por ejemplo, puedes comprobar si un trigger ha tocado exactamente el objeto enlazado:
export const properties = {
target: { type: "object", label: "Target", default: "" }
};
export function onTriggerEnter(object, collision, properties) {
if (String(collision.other.id) === properties.target) {
Debug.log("The selected target entered the trigger");
}
}
Enlazar assets
export const properties = {
texture: { type: "texture", label: "Texture", default: "" },
sound: { type: "sound", label: "Sound", default: "" },
animation: { type: "animation", label: "Animation", default: "" }
};
export function start(object, properties) {
if (properties.texture) object.texture = properties.texture;
Debug.log({ sound: properties.sound, animation: properties.animation });
}
Tipos disponibles: number, boolean, string, color, select, object, texture, sound, animation y prefab. Tambien puedes leer los mismos valores mediante object.scriptProperties. En start, properties es el segundo argumento. En update, fixedUpdate, pausedUpdate, lateUpdate y los callbacks de colision es el tercero.
Si un objeto tiene isStatic = true, se recomienda no moverlo, rotarlo, escalarlo ni cambiar
su jerarquia durante Play. Esta marca sirve para que el motor pueda optimizar render, colisiones,
navegacion y otros sistemas en el futuro.
Ciclo de activacion: si active es false, no se ejecutan
los componentes, las colisiones ni el script del objeto. Tambien se aplica cuando uno de sus padres
esta inactivo. Si se activa despues de iniciar la escena, start(object) se ejecuta
entonces una sola vez y antes del primer update(object, deltaTime). Los componentes
automaticos, como Audio Source / Play On Start, arrancan al activarse.
8. API de debug
Los mensajes aparecen en la pestaña Console del panel inferior del editor.
| Funcion | Uso | Ejemplo |
|---|---|---|
debug(value) | Muestra cualquier valor. | debug("Hola") |
Debug.log(value) | Mensaje normal. | Debug.log(object.name) |
Debug.warn(value) | Mensaje de aviso. | Debug.warn("Vida baja") |
Debug.error(value) | Mensaje de error. | Debug.error("No hay objetivo") |
Debug.clear() | Limpia la consola. | Debug.clear() |
export function start(object) {
Debug.log({ nombre: object.name, posicion: { x: object.x, y: object.y } });
}
9. Esperas con Wait
Wait permite pausar una funcion asincrona, parecido a una corrutina. Para usarlo, la
funcion debe declararse con async.
| Funcion | Uso | Ejemplo |
|---|---|---|
await Wait.seconds(segundos) | Espera una cantidad de segundos. | await Wait.seconds(0.2) |
await Wait.frames(frames) | Espera una cantidad de frames. | await Wait.frames(1) |
export async function start(object) {
object.color = "#ff0000";
await Wait.seconds(0.2);
object.color = "#ffffff";
}
export async function start(object) {
debug("3");
await Wait.seconds(1);
debug("2");
await Wait.seconds(1);
debug("1");
}
Animaciones de propiedades con Tween
Tween cambia suavemente propiedades numericas durante Play. Sirve para mover, rotar,
escalar o desvanecer objetos sin programar la interpolacion dentro de update.
La duracion y los retrasos se expresan en segundos.
| Funcion | Uso | Ejemplo |
|---|---|---|
Tween.to(target, values, duration, options) | Anima desde los valores actuales hasta los indicados. | Tween.to(object, { x: 400 }, 1) |
Tween.from(target, values, duration, options) | Coloca los valores iniciales y anima hasta los que tenia el objeto. | Tween.from(object, { opacity: 0 }, 0.5) |
Tween.cancel(target) | Cancela todos los tweens de un objeto. | Tween.cancel(object) |
Tween.cancel(target, property) | Cancela solo los tweens de una propiedad. | Tween.cancel(object, "x") |
Tween.cancelAll() | Cancela todos los tweens activos. | Tween.cancelAll() |
Tween.isTweening(target, property) | Comprueba si existe un tween activo. | Tween.isTweening(object, "x") |
Tween.pauseAll() | Pausa todos los tweens. | Tween.pauseAll() |
Tween.resumeAll() | Reanuda todos los tweens. | Tween.resumeAll() |
export function start(object) {
Tween.to(object, {
x: object.x + 240,
rotation: 360,
scaleX: 2,
scaleY: 2
}, 1.5, {
ease: "cubicInOut",
yoyo: true,
repeat: 1
});
}
Opciones disponibles: ease, delay, repeat,
repeatDelay, yoyo, paused, overwrite,
onStart, onUpdate, onRepeat, onComplete y
onCancel. Por defecto, un tween nuevo cancela tweens anteriores que modifiquen las
mismas propiedades del mismo objeto. Usa overwrite: false para permitirlos.
Curvas incluidas: linear, easeIn, easeOut,
easeInOut, quadIn, quadOut, quadInOut,
cubicIn, cubicOut, cubicInOut, backIn,
backOut, sineIn, sineOut y sineInOut.
export async function start(object) {
const movement = Tween.to(object, { y: object.y - 100 }, 0.8, {
ease: "backOut"
});
const result = await movement;
debug(result.status); // "completed" o "cancelled"
}
El valor devuelto permite pause(), resume(), cancel() y
complete(). Tambien se puede esperar directamente con await. Los tweens
se cancelan automaticamente al salir de Play, destruir su objeto o cambiar de escena.
Tween solo interpola propiedades numericas. Si un componente fisico o un script modifica al mismo tiempo la misma propiedad, ambos sistemas competiran por el valor.
10. Buscar objetos
| Funcion | Devuelve | Ejemplo |
|---|---|---|
FindByName(name) | El primer objeto con ese nombre o null. | FindByName("Player") |
FindByTag(tag) | El primer objeto con ese tag o null. | FindByTag("Enemy") |
FindAllByName(name) | Array con todos los objetos activos que tengan ese nombre. | FindAllByName("Coin") |
FindAllByTag(tag) | Array con todos los objetos activos que tengan ese tag. | FindAllByTag("Enemy") |
FindAllByComponent(type) | Array de objetos activos con ese componente. | FindAllByComponent("PhysicsBody") |
FindAllInArea(x, y, w, h) | Objetos activos cuyos limites se solapan con el rectangulo indicado. | FindAllInArea(0, 0, 800, 600) |
export function start(object) {
const player = FindByName("Player");
if (player) {
debug("Jugador encontrado en X: " + player.x);
}
}
export function update(object, deltaTime) {
const target = FindByTag("Target");
if (!target) return;
object.x += Math.sign(target.x - object.x) * 80 * deltaTime;
}
Grupos temporales
Groups permite reunir objetos durante Play sin cambiar su nombre, tag o jerarquia.
Los grupos se vacian automaticamente al cambiar de escena.
Groups.create(name, objects) | Crea un grupo y anade una lista opcional. |
Groups.add(name, object) | Anade un objeto. |
Groups.remove(name, object) | Quita un objeto. |
Groups.get(name) | Devuelve los miembros validos. |
Groups.has(name, object) | Comprueba si pertenece al grupo. |
Groups.forEach(name, callback) | Ejecuta una funcion para cada miembro. |
Groups.setActive(name, active) | Activa o desactiva todos sus miembros. |
Groups.clear(name) | Vacia el grupo. |
Groups.delete(name) | Elimina el grupo. |
Groups.names() | Devuelve todos los nombres de grupo. |
export function start(object) {
const enemies = FindAllByTag("Enemy");
Groups.create("wave", enemies);
}
export function update(object) {
if (Input.getKeyDown("K")) {
Groups.setActive("wave", false);
}
}
11. Destruir objetos
| Funcion | Uso | Ejemplo |
|---|---|---|
Destroy(object) | Destruye un objeto al momento. | Destroy(enemy) |
Destroy(object, tiempo) | Destruye un objeto tras unos segundos. | Destroy(object, 2) |
Si destruyes un objeto que tiene hijos, tambien se destruyen sus hijos. Destroy solo debe
usarse durante Play.
export function start(object) {
Destroy(object, 3);
}
export function update(object, deltaTime) {
const enemy = FindByTag("Enemy");
if (enemy && enemy.x < -500) {
Destroy(enemy);
}
}
Instanciar prefabs desde codigo
Prefab permite crear copias de prefabs durante Play. El prefab debe existir en la pestana
Prefabs del proyecto.
| Funcion | Uso | Ejemplo |
|---|---|---|
await Prefab.instantiate(nombre) | Crea una copia del prefab. | await Prefab.instantiate("Enemy") |
await Prefab.instantiate(nombre, opciones) | Crea una copia con posicion, nombre o padre. | await Prefab.instantiate("Bullet", { x: 100, y: 40 }) |
await Prefab.instantiateMany(nombre, opciones[]) | Crea muchas copias en una sola operacion optimizada y devuelve un array con sus objetos raiz. | await Prefab.instantiateMany("Tile", [{ x: 0, y: 0 }, { x: 64, y: 0 }]) |
await Prefab.create(nombre, opciones) | Alias de instantiate. | await Prefab.create("Coin") |
await Prefab.spawn(nombre, opciones) | Alias de instantiate. | await Prefab.spawn("Explosion") |
Si el prefab tiene un solo objeto raiz, la funcion devuelve ese objeto. Si el prefab tiene varios objetos raiz, devuelve una lista. Los scripts del prefab se cargan y empiezan a ejecutarse en Play.
| Opcion | Tipo | Descripcion |
|---|---|---|
x | number | Posicion X del objeto raiz. |
y | number | Posicion Y del objeto raiz. |
offsetX | number | Desplazamiento X si no indicas x e y. |
offsetY | number | Desplazamiento Y si no indicas x e y. |
name | string | Nombre base para la copia creada. |
parent | object | Objeto que sera el padre del prefab instanciado. |
rotation | number | Rotacion inicial del objeto raiz. |
scaleX | number | Escala X inicial del objeto raiz. |
scaleY | number | Escala Y inicial del objeto raiz. |
export async function start() {
const positions = Array.from({ length: 100 }, (_, index) => ({
x: (index % 10) * 64,
y: Math.floor(index / 10) * 64
}));
const tiles = await Prefab.instantiateMany("Tile", positions);
tiles.forEach((tile, index) => {
tile.name = `Tile_${index}`;
});
}
Usa instantiateMany cuando todas las copias deban crearse al mismo tiempo, por ejemplo
para tableros, mapas o grupos iniciales. Para balas, enemigos u objetos que aparecen individualmente
durante la partida, usa Prefab.instantiate o Pool.
export async function start(object) {
const enemy = await Prefab.instantiate("Enemy", {
x: object.x + 120,
y: object.y,
name: "EnemySpawned"
});
debug(enemy.name);
}
export async function start(object) {
await Wait.seconds(1);
const bullet = await Prefab.instantiate("Bullet", {
x: object.x + 32,
y: object.y,
parent: object
});
bullet.translate(10, 0);
}
Prefab.instantiate solo se usa durante Play y necesita Tauri para leer el prefab guardado
en el proyecto.
Pool de prefabs
Pool precarga copias inactivas y las reutiliza. Es recomendable para balas, enemigos,
monedas y explosiones que aparecen muchas veces.
await Pool.create(name, prefab, size) | Crea el pool y precarga la cantidad indicada. |
await Pool.spawn(name, { x, y }) | Obtiene y activa una copia. Si no queda ninguna, amplía el pool por defecto. |
Pool.release(object) | Desactiva y devuelve el objeto a su pool. |
Pool.releaseAll(name) | Devuelve todos los miembros activos. |
Pool.get(name) | Devuelve tamaño, activos y disponibles. |
Pool.has(name) | Comprueba si existe. |
Pool.clear(name) | Elimina el registro del pool. |
export async function start(object) {
await Pool.create("bullets", "Bullet", 32);
}
export async function update(object) {
if (Input.getKeyDown("Space")) {
const bullet = await Pool.spawn("bullets", {
x: object.x + 24,
y: object.y
});
Physics.setVelocity(bullet, 500, 0);
}
}
export function recycleBullet(bullet) {
Pool.release(bullet);
}
Los pools son temporales y se limpian al cambiar de escena. Usa Pool.release en vez de
Destroy para devolver una instancia reutilizable.
12. Cargar escenas
Scene.load carga una escena del proyecto por nombre. Durante Play mantiene el juego en
marcha, cambia a la nueva escena y arranca los scripts de los objetos de esa escena.
| Funcion | Uso | Ejemplo |
|---|---|---|
await Scene.load(nombre) | Carga una escena por nombre. | await Scene.load("Level1") |
await Scene.load(nombre, opciones) | Permite una transicion de fundido. | await Scene.load("Boss", { transition: "fade", duration: 0.4 }) |
await Scene.reload() | Recarga la escena actual. | await Scene.reload() |
await Scene.preload(nombre) | Lee y deja preparada una escena para acelerar el siguiente load. | await Scene.preload("Boss") |
Scene.current | Nombre de la escena actual. | debug(Scene.current) |
Scene.getCurrent() | Devuelve el nombre de la escena actual. | Scene.getCurrent() |
Scene.onLoad(callback) | Registra una funcion al terminar una carga y devuelve una funcion para cancelarla. | Scene.onLoad(name => debug(name)) |
Scene.onUnload(callback) | Registra una funcion antes de abandonar la escena. | Scene.onUnload(name => debug(name)) |
export async function start(object) {
await Wait.seconds(2);
await Scene.load("Level1");
}
Transicion Fade
Puedes pasar opciones como segundo parametro. Con transition: "fade", la pantalla se
funde a negro, el motor cambia de escena cuando ya esta cubierta y despues muestra gradualmente la
nueva escena. Usa duration para indicar los segundos de cada fase del fundido.
export async function update(object) {
if (object.x > 800) {
await Scene.load("Level2", {
transition: "fade",
duration: 0.4
});
}
}
Usa await para esperar hasta que la carga y el fundido hayan terminado. Si omites
duration, se usan 0.3 segundos. Sin opciones, el cambio es inmediato:
await Scene.load("Level2").
export async function update(object, deltaTime) {
if (object.x > 800) {
await Scene.load("NextLevel");
}
}
El nombre debe coincidir con una escena existente del proyecto. No escribas la extension del archivo.
Scene.vars, los grupos y los pools se reinician al cambiar de escena.
13. API de animaciones
Animaciones Sprite y Property
El editor separa los dos sistemas para que no se mezclen. La pestana Animations contiene exclusivamente clips Sprite con texturas y FPS. La pestana Timeline contiene exclusivamente clips Property organizados mediante pistas y fotogramas clave.
Para crear un clip de propiedades abre Timeline y pulsa New Property. Asigna despues ese clip desde el campo Animation Timeline del Inspector del objeto. Timeline usa automaticamente ese objeto como Target Object; no se selecciona dentro del editor. El nombre y el ID indican siempre que objeto se esta editando. Elige una pista y coloca el cursor en el tiempo deseado. Pulsa Add/Update Key para capturar el valor actual del objeto. Modifica el objeto, mueve el tiempo y anade otra clave; el motor interpolara los valores entre ambas.
Para asignarlo a un objeto usa el campo Animation Timeline de la seccion Timeline Animator del Inspector. El campo Animation queda reservado exclusivamente para animaciones Sprite. Al abrir la pestana Timeline con ese objeto seleccionado, el editor carga su clip asignado y permite verlo con Play.
| Pista | Propiedad animada |
|---|---|
Position X / Y | Posicion local x e y. |
Rotation | Rotacion del objeto en grados. |
Scale X / Y | Escala independiente de cada eje. |
Opacity | Opacidad interpolada del objeto. |
Color | Color interpolado entre dos claves. |
- Duration define la duracion total del clip en segundos.
- Target Object muestra automaticamente el objeto que tiene el clip asignado en su campo Animation Timeline.
- Local Position marcado aplica el desplazamiento del clip desde la posicion inicial de cada objeto; desmarcado usa los valores X/Y absolutos del clip.
- El panel Timeline se acopla en la parte inferior del editor para mantener visible la escena mientras transformas el objeto.
- La linea roja es el cabezal de reproduccion: indica el instante actual y avanza sobre las pistas durante la previsualizacion.
- Play reproduce desde el tiempo actual, Pause y Stop conservan la posicion, y Rewind vuelve al inicio.
- Los controles de reproduccion conservan el zoom y la zona visible del Timeline.
- Activa Follow Playhead para que la vista horizontal siga automaticamente la linea roja durante la reproduccion.
- Al mover el cursor se actualizan en vivo posicion, escala, rotacion, opacidad y color del objeto objetivo.
- Al cerrar Timeline, cambiar de pestana o entrar en Play se restaura automaticamente el estado original.
- Loop repite el clip continuamente.
- Pingpong reproduce de ida y vuelta cuando Loop esta activo.
- Pulsa un rombo para seleccionar su tiempo.
- Arrastra un rombo horizontalmente con el raton para cambiar el tiempo de ese fotograma clave y previsualizar el resultado.
- Selecciona un rombo y pulsa Duplicate Key para copiarlo 0,10 segundos mas adelante.
- Usa Zoom - y Zoom + para comprimir o ampliar horizontalmente el Timeline entre 50% y 400%.
- Pulsa con el boton derecho sobre un rombo para eliminar esa clave.
Los clips Property se asignan y reproducen desde el Inspector igual que los clips Sprite. Tambien
funcionan con la misma API Animations y se incluyen en el juego exportado.
Control desde scripts
Animations permite asignar y controlar animaciones desde un script. Puedes usar el ID o
el nombre de la animacion.
| Funcion | Uso | Ejemplo |
|---|---|---|
Animations.find(nombreOId) | Busca una animacion. | Animations.find("Run") |
Animations.assign(object, nombreOId) | Asigna una animacion al objeto. | Animations.assign(object, "Run") |
Animations.play(object) | Reproduce la animacion asignada. | Animations.play(object) |
Animations.play(object, nombreOId) | Asigna y reproduce una animacion. | Animations.play(object, "Jump") |
Animations.stop(object) | Detiene la animacion. | Animations.stop(object) |
Animations.enable(object) | Activa que arranque automaticamente en Play. | Animations.enable(object) |
Animations.disable(object) | Desactiva el arranque automatico y la detiene. | Animations.disable(object) |
Animations.activate(object) | Alias de enable. | Animations.activate(object) |
Animations.deactivate(object) | Alias de disable. | Animations.deactivate(object) |
export function start(object) {
Animations.assign(object, "Idle");
Animations.play(object);
}
export async function start(object) {
Animations.play(object, "Hit");
await Wait.seconds(0.5);
Animations.play(object, "Idle");
}
14. API de particulas
Particles permite asignar y controlar sistemas de particulas desde un script. Puedes usar
el ID o el nombre del sistema.
En la pestaña Particles puedes empezar con los templates Explosion, Fire, Smoke, Sparks, Snow, Rain y Magic. Apply sustituye los ajustes del sistema seleccionado, pero conserva su nombre e ID. Si no eliges una textura, Shape dibuja partículas Circle, Square, Triangle, Diamond o Star. Ajusta emisión, ráfaga, vida, duración, velocidad, dirección, gravedad, tamaño, color y opacidad antes de asignarlo a un objeto.
| Funcion | Uso | Ejemplo |
|---|---|---|
Particles.find(nombreOId) | Busca un sistema de particulas. | Particles.find("Explosion") |
Particles.assign(object, nombreOId) | Asigna particulas al objeto. | Particles.assign(object, "Smoke") |
Particles.play(object) | Reproduce las particulas asignadas. | Particles.play(object) |
Particles.play(object, nombreOId) | Asigna y reproduce particulas. | Particles.play(object, "Explosion") |
Particles.stop(object) | Detiene las particulas. | Particles.stop(object) |
Particles.enable(object) | Activa que arranquen automaticamente en Play. | Particles.enable(object) |
Particles.disable(object) | Desactiva el arranque automatico y las detiene. | Particles.disable(object) |
Particles.activate(object) | Alias de enable. | Particles.activate(object) |
Particles.deactivate(object) | Alias de disable. | Particles.deactivate(object) |
export function start(object) {
Particles.assign(object, "Smoke");
Particles.play(object);
}
export async function start(object) {
Particles.play(object, "Explosion");
await Wait.seconds(1);
Destroy(object);
}
15. Ejemplos completos
Mover un objeto
export function update(object, deltaTime) {
object.x += 120 * deltaTime;
}
Rotar constantemente
export function update(object, deltaTime) {
object.rotation += 180 * deltaTime;
}
Parpadear cambiando opacidad
let time = 0;
export function update(object, deltaTime) {
time += deltaTime;
object.opacity = 0.5 + Math.sin(time * 8) * 0.5;
}
Seguir al jugador
export function update(object, deltaTime) {
const player = FindByName("Player");
if (!player) return;
const speed = 90;
object.x += Math.sign(player.x - object.x) * speed * deltaTime;
object.y += Math.sign(player.y - object.y) * speed * deltaTime;
}
Eliminar enemigos por tag
export function start(object) {
const enemy = FindByTag("Enemy");
if (enemy) {
Destroy(enemy, 1.5);
}
}
Cambiar de escena tras una espera
export async function start(object) {
debug("Cargando siguiente nivel...");
await Wait.seconds(1);
await Scene.load("Level2");
}
Follow Camera
La camara de Play puede seguir automaticamente a un objeto por tag. En el panel izquierdo
Scene > Camera, activa Follow Player y elige el tag del objeto
que quieres seguir, por ejemplo Player.
| Propiedad | Uso |
|---|---|
Follow Player | Activa el seguimiento de camara durante Play. |
Tag | Tag del objeto que seguira la camara. La lista sale de los tags de la escena. |
Dead Zone X/Y | Zona muerta antes de mover la camara. Sirve para que el personaje pueda moverse un poco sin arrastrar la camara. |
Smooth | Respuesta del seguimiento entre 0 y 1. 0 no mueve la camara, 1 sigue inmediatamente. |
Lock X/Y | Bloquea el seguimiento en un eje. |
Offset X/Y | Desplaza el punto de seguimiento respecto al centro del objeto. |
Bounds | Limita la camara dentro de un rectangulo de mundo con min/max X/Y. |
Effect | Filtro visual aplicado solo durante Play: None, Scanlines, CRT, Noir, Sepia o Dream. |
FX | Intensidad del efecto entre 0 y 1. |
Scanline Size | Separacion de las lineas cuando usas Scanlines o CRT. |
Vignette | Oscurece suavemente los bordes de la camara. |
Noise | Anade ruido ligero tipo pantalla antigua. Tambien se activa con CRT. |
Los fondos con componente Parallax usan esta camara cuando no tienen target manual. Por eso el parallax se mueve de forma natural al activar Follow Player.
API de Camera
Camera permite mover la camara de juego desde scripts durante Play. Si
Follow Player esta activo, el seguimiento puede volver a moverla en el siguiente
frame; usa { disableFollow: true } cuando quieras colocarla manualmente.
| Funcion | Uso | Ejemplo |
|---|---|---|
Camera.moveTo(x, y) | Mueve la esquina superior izquierda de la camara a una posicion del mundo. | Camera.moveTo(400, 120) |
Camera.setPosition(x, y) | Alias de moveTo. | Camera.setPosition(0, 0) |
Camera.centerOn(x, y) | Centra la camara en un punto del mundo. | Camera.centerOn(player.x, player.y) |
Camera.getPosition() | Devuelve { x, y } con la posicion actual de la camara. | const pos = Camera.getPosition() |
Camera.getRect(margen) | Devuelve el rectangulo visible de camara con margen opcional. | const rect = Camera.getRect(32) |
Camera.isObjectOutside(object, margen) | Indica si el objeto completo esta fuera de camara. El margen opcional amplía el rectangulo. | Camera.isObjectOutside(enemy, 64) |
object.isOutsideCamera(margen) | Metodo directo del objeto para saber si salio de camara. | object.isOutsideCamera(64) |
await Camera.fadeOut(tiempo, color) | Oscurece la camara hasta cubrirla con el color indicado. El color por defecto es negro. | await Camera.fadeOut(1) |
await Camera.fadeIn(tiempo, color) | Quita el color de fade y vuelve a mostrar la escena. | await Camera.fadeIn(0.8, "#000") |
await Camera.fade(tipo, tiempo, color) | Funcion generica. tipo puede ser "in" o "out". | await Camera.fade("out", 1, "black") |
Camera.cutToBlack(color) | Corte instantaneo a color, por defecto negro. | Camera.cutToBlack() |
Camera.clearFade() | Quita cualquier fade activo de forma instantanea. | Camera.clearFade() |
export function start(object) {
Camera.moveTo(0, 0, { disableFollow: true });
}
export function update(object) {
const player = FindByTag("Player");
if (player && Input.getKeyDown("C")) {
Camera.centerOn(player.x, player.y, { disableFollow: true });
}
}
Detectar salida de camara
export function update(object) {
object.translate(300 * deltaTime, 0);
if (object.isOutsideCamera(64)) {
Destroy(object);
}
}
Fade para cambio de escena
export async function start(object) {
await Camera.fadeOut(1, "#000000");
await Scene.load("Level2");
await Camera.fadeIn(1, "#000000");
}
16. UI Canvas
La UI de usuario se dibuja dentro del canvas del juego. En el editor se coloca dentro del rectangulo de camara y en Play aparece como Screen Space Overlay, encima de la escena y sin moverse con la camara del mundo.
Desde Add GameObject puedes crear: UI Canvas, UI Panel,
UI Text, UI Image, UI Button, UI Input,
UI Checkbox, UI Select, UI Progress Bar, UI Slider y UI Video.
| Control | Uso |
|---|---|
UI Panel | Fondo o contenedor visual. Los hijos UI se colocan relativos al panel en Play. |
UI Text | Texto para puntuacion, mensajes, nombres o etiquetas. Puede mantener la tipografia sin deformar al escalar y mostrar un color de fondo opcional. |
UI Image | Imagen desde Textures o bloque de color si no tiene imagen asignada. No usa texto ni fuente. |
UI Button | Boton interactivo con imagen opcional, texto y fondo con opacidad independiente. Dispone de sombras separadas y estados visuales de imagen para Hover y Pressed mediante tinte, escala y transición. |
UI Input | Campo editable durante Play. En móvil abre automáticamente el teclado virtual del sistema. |
UI Checkbox | Valor verdadero/falso interactivo. Tiene color Hover al pasar el puntero por encima. |
UI Select | Lista desplegable estilo HTML select. En Play abre sus opciones, resalta la opcion bajo el puntero, permite elegir una y dispara UI.onChange al cambiar. Si hay demasiadas opciones muestra barra de desplazamiento. |
UI Progress Bar | Barra no interactiva para vida, energia, carga o experiencia. Usa Value, Min, Max y color Fill. |
UI Slider | Control interactivo de valor numerico. En Play se puede arrastrar y dispara UI.onChange. |
UI Video | Vídeo anclado a la pantalla para menús, cinemáticas o tutoriales. Admite ajuste, reproducción inicial, bucle, silencio y volumen. |
Canvas UI en móvil
Los controles interactivos de Canvas UI funcionan tanto con ratón como con pantalla táctil:
UI Button, UI Checkbox, UI Select y UI Slider
responden al dedo. Al tocar un UI Input, GameCrom abre el teclado virtual del móvil y
sincroniza el texto con UI.getValue y UI.onChange.
En el Inspector, Input Type permite elegir Text, Number,
Email o Password. Esta opción solicita al dispositivo el teclado más
adecuado. Password oculta visualmente los caracteres, aunque el valor continúa
disponible para el script como texto. Los elementos puramente visuales —paneles, textos,
imágenes y barras de progreso— se muestran normalmente en móvil, pero no capturan pulsaciones.
La UI usa Rect Transform: Anchor, Pivot, offset X/Y,
tamano y orden Z. Para crear ventanas, haz un UI Panel y mete textos,
botones, inputs, checks, selects, sliders o barras como hijos en la jerarquia.
Anchor funciona como preset: al elegir Center, Top Right,
Bottom, etc. el control se coloca en esa zona, ajusta su Pivot y deja
el offset X/Y a cero. Despues puedes moverlo con X/Y como margen desde ese anchor.
En Play los hijos UI se dibujan encima de su padre aunque tengan menor Z. Todos los
controles tienen Opacity. El campo Font permite elegir Arial
o cualquier fuente importada en Fonts.
Los controles con texto tienen Align y V Align para alinear el texto
a izquierda, centro, derecha, arriba, medio o abajo.
UI Text puede activar Multiline para trabajar como bloque de texto:
acepta saltos de linea con \n, Word Wrap, Line Height,
Max Lines y Overflow en modo Clip,
Visible o Ellipsis.
Los objetos UI tambien pueden llevar un Script igual que cualquier otro objeto:
reciben start(object) y update(object, deltaTime) solo durante Play.
En UI Select, las opciones se editan en el Inspector como una lista: puedes añadir,
borrar y cambiar cada opción por separado.
Visible Rows controla cuantas opciones se ven antes de activar scroll y
Row Height permite ajustar la altura de cada fila del desplegable.
UI Panel y UI Button tienen Corner Radius para redondear bordes.
Sombra y contorno de la UI
Los elementos UI admiten Shadow en el Inspector: desplazamiento X/Y, color, opacidad de 0 a 1 y desenfoque (Shadow Blur). En UI Text también puedes activar Text Outline y elegir su color y anchura. El efecto se escala con la interfaz tanto en Play como en las compilaciones; deja espacio alrededor del texto si usas una sombra o un contorno grande.
Todos los controles con texto incluyen el selector Text Style: Normal, Bold, Italic, Bold Italic, Underline y Strikethrough. Está disponible en UI Text, Button, Input, Checkbox, Select y Touch Button.
API de UI
| Funcion | Uso | Ejemplo |
|---|---|---|
UI.find(name) | Busca un objeto UI por nombre. | UI.find("ScoreText") |
UI.setFocus(target) | Selecciona un control interactivo visible. Devuelve false si no se puede seleccionar. | UI.setFocus("PlayButton") |
UI.getFocused() | Devuelve el control seleccionado o null. | UI.getFocused() |
UI.clearFocus() | Quita la selección actual. | UI.clearFocus() |
UI.setNavigationEnabled(enabled) | Activa o desactiva la navegación automática para no interferir con los controles del juego. | UI.setNavigationEnabled(false) |
UI.show(target) | Muestra y activa un control. | UI.show("PausePanel") |
UI.hide(target) | Oculta un control en Play. | UI.hide("PausePanel") |
UI.setText(target, text) | Cambia el texto visible. | UI.setText(score, "100") |
UI.getValue(target) | Lee input, checkbox, select, slider, progress bar o texto. | UI.getValue("VolumeSlider") |
UI.setValue(target, value) | Cambia el valor interno. | UI.setValue("MusicCheck", true) |
UI.setRange(target, min, max, value) | Cambia rango y valor de slider o progress bar. | UI.setRange("HealthBar", 0, 100, 75) |
UI.setImage(target, texture) | Cambia la textura de una imagen UI. | UI.setImage(icon, "coin.png") |
UI.setButtonColors(target, normal, hover, pressed) | Cambia los colores normal, hover y pulsado de un boton. | UI.setButtonColors("PlayButton", "#1f8fff", "#2fb0ff", "#0d4f9a") |
UI.clear(target) | Limpia el valor de un input. | UI.clear("NameInput") |
UI.onClick(target, fn) | Escucha activaciones de botones por ratón, teclado o mando. | UI.onClick(button, fn) |
UI.onChange(target, fn) | Escucha cambios de input, checkbox, select o slider. | UI.onChange(slider, fn) |
Los botones, inputs, casillas, selectores y sliders visibles e interactivos se pueden recorrer con flechas, cruceta o stick izquierdo. Enter, Espacio o A activan el control; B quita el foco. En un selector abierto, las direcciones cambian la opción; en un slider, izquierda y derecha ajustan el valor. El foco se muestra con un marco azul. No se selecciona nada hasta usar un control o llamar a UI.setFocus.
// Menu simple: funciona con raton, teclado y mando.
export function start(object) {
const play = UI.find("PlayButton");
const options = UI.find("OptionsButton");
UI.setFocus(play); // Optional: choose the initial button.
UI.onClick(play, () => Scene.load("Level1"));
UI.onClick(options, () => UI.show("OptionsPanel"));
}
export function start(object) {
const score = UI.find("ScoreText");
const button = UI.find("StartButton");
UI.setText(score, "Score: 0");
UI.onClick(button, () => {
Scene.load("Level1");
});
}
// UI Text multiline.
export function start(object) {
UI.setText("DialogText", "Linea 1\nLinea 2\nLinea 3");
}
// Script asignado directamente a un UI Button.
export function start(object) {
UI.onClick(object, () => {
debug("Boton pulsado");
});
}
// Progress Bar: mostrar vida del jugador.
let vida = 100;
export function start(object) {
const healthBar = UI.find("HealthBar");
const healthText = UI.find("HealthText");
UI.setRange(healthBar, 0, 100, vida);
UI.setText(healthText, `Vida: ${vida}`);
}
export function update(object, deltaTime) {
const healthBar = UI.find("HealthBar");
const healthText = UI.find("HealthText");
// Ejemplo: la vida baja poco a poco.
vida = Math.max(vida - 5 * deltaTime, 0);
UI.setValue(healthBar, vida);
UI.setText(healthText, `Vida: ${Math.round(vida)}`);
}
// Slider: mostrar el valor en un UI Text.
export function start(object) {
const slider = UI.find("VolumeSlider");
const valueText = UI.find("VolumeValueText");
UI.setRange(slider, 0, 100, 50);
UI.setText(valueText, "Volumen: 50");
UI.onChange(slider, () => {
const value = Math.round(UI.getValue(slider));
UI.setText(valueText, `Volumen: ${value}`);
});
}
17. Componentes
Los componentes anaden comportamiento o datos extra a un objeto. Selecciona un objeto, pulsa Add Component en el Inspector y busca el componente que quieres anadir.
El menú Add Component contiene estos 15 componentes. Las secciones siguientes conservan sus explicaciones, propiedades, API y ejemplos.
| Componente | Para qué sirve |
|---|---|
| Video Renderer | Reproduce un vídeo dentro de los límites de un objeto del mundo. |
| Audio Source | Reproduce un sonido asignado al objeto. |
| Audio Effect | Añade efectos encadenados al Audio Source; admite varios en el mismo objeto. |
| Physics Body | Velocidad, gravedad, masa y respuesta física. |
| Parallax | Desplaza una textura en relación con la cámara o un objetivo. |
| Character Controller | Movimiento de personaje de plataformas o vista superior. |
| Ladder | Marca un área escalable para Character Controller. |
| Moving Platform | Mueve una plataforma y puede transportar pasajeros. |
| Conveyor Belt | Desplaza personajes y cuerpos físicos que están encima. |
| Texture Scroller | Anima el desplazamiento de la textura. |
| Waypoint Mover | Recorre puntos configurables. |
| Pathfinding Agent | Busca rutas alrededor de obstáculos. |
| Look At Target | Orienta el objeto hacia un objetivo. |
| Rotation | Gira el objeto de forma continua o durante una vuelta. |
| Bouncy Ball | Mueve y hace rebotar una bola sin Physics Body. |
Collider 2D, Sprite Renderer, Timeline Animator, Script y Particle System son apartados integrados del Inspector, no entradas de este menú. Light 2D y Pixel Canvas son tipos de GameObject; los controles UI se crean desde Add GameObject.
Video Renderer
Importa el archivo en Videos y añade este componente a un objeto normal. El vídeo se dibuja dentro de sus límites; no es un control UI. Para mostrarlo fijo en pantalla utiliza UI Video.
| Propiedad | Uso |
|---|---|
Video | Archivo de vídeo importado. |
Fit | Contain conserva todo el vídeo, Cover rellena recortando y Stretch ajusta sin conservar proporciones. |
Play On Start, Loop | Reproducción automática al iniciar y repetición. |
Muted, Volume | Silencio y volumen de 0 a 1. El navegador puede bloquear la reproducción automática con sonido. |
Enabled | Activa o desactiva el componente. |
Ladder
Coloca este componente en el objeto que representa una escalera. Al añadirlo se activan Collision y Trigger; un Character Controller en modo Platformer con Use Ladders puede subir o bajar por ella. Enabled permite desactivarla sin eliminarla.
Moving Platform
Mueve el objeto entre su posición inicial y el desplazamiento configurado. Move X/Y fija el recorrido en píxeles, Speed la velocidad, Ping Pong el viaje de vuelta y Carry Riders si transporta a los personajes que están encima. Enabled detiene o reanuda el componente. El objeto necesita una colisión apropiada para servir de plataforma.
Rotation
Gira el objeto durante Play. Speed indica grados por segundo; un valor negativo invierte el sentido. Pivot X/Y desplaza el centro de giro y permite hacer órbitas. Con Loop desmarcado se detiene tras una vuelta completa. Enabled activa o desactiva el giro.
Audio Source
Audio Source reproduce sonidos del proyecto desde un objeto. Sus parametros son: sonido, volumen, pitch, loop, play on start y enabled.
Los sonidos del proyecto se cargan en memoria al abrir/refrescar el proyecto. Audio Source no carga sonidos en caliente durante Play; si un sonido no esta precargado, se mostrara un error.
| Propiedad | Uso |
|---|---|
Sound | Archivo de sonido importado en la pestana Sounds. |
Volume | Volumen entre 0 y 1. |
Pitch | Tono y velocidad entre 0.1 y 4. Menos de 1 suena más grave y más lento; más de 1 suena más agudo y rápido. El valor 1 conserva el sonido original. |
Loop | Repite el sonido automaticamente. |
Play On Start | Reproduce el sonido al entrar en Play. |
Enabled | Activa o desactiva el componente. |
API de AudioSource
| Funcion | Uso | Ejemplo |
|---|---|---|
AudioSource.get(object) | Devuelve el componente Audio Source del objeto. | AudioSource.get(object) |
await AudioSource.play(object) | Reproduce el sonido asignado. | await AudioSource.play(object) |
AudioSource.pause(object) | Pausa la reproduccion actual. | AudioSource.pause(object) |
AudioSource.stop(object) | Detiene y vuelve al inicio. | AudioSource.stop(object) |
AudioSource.fadeIn(object, tiempo) | Inicia el sonido y sube suavemente desde silencio hasta el volumen configurado. | AudioSource.fadeIn(object, 0.1) |
AudioSource.fadeOut(object, tiempo) | Baja suavemente el volumen hasta cero y detiene el sonido sin producir un corte brusco. | AudioSource.fadeOut(object, 0.1) |
AudioSource.isPlaying(object) | Indica si esta sonando. | AudioSource.isPlaying(object) |
AudioSource.setSound(object, sound) | Cambia el sonido. | AudioSource.setSound(object, "jump.wav") |
AudioSource.setVolume(object, volume) | Cambia el volumen. | AudioSource.setVolume(object, 0.5) |
AudioSource.getPitch(object) | Devuelve el pitch actual. | AudioSource.getPitch(object) |
AudioSource.setPitch(object, pitch) | Cambia velocidad y tono entre 0.1 y 4. | AudioSource.setPitch(object, 1.5) |
AudioSource.setLoop(object, loop) | Activa o desactiva loop. | AudioSource.setLoop(object, true) |
AudioSource.setEnabled(object, enabled) | Activa o desactiva el componente. | AudioSource.setEnabled(object, false) |
export async function start(object) {
AudioSource.setVolume(object, 0.7);
AudioSource.setPitch(object, 1.2);
await AudioSource.play(object);
}
export function update(object) {
if (Input.getKeyDown("Space")) {
AudioSource.play(object);
}
}
Audio Effect
Audio Effect procesa el sonido del Audio Source que esta en el mismo objeto. Se pueden anadir varios Audio Effect: el motor los conecta en el mismo orden en que aparecen en la lista de componentes.
El objeto necesita un Audio Source. Por ejemplo, puedes encadenar
Filter → Delay → Reverb. En equipos de poca potencia conviene limitar el numero de
reverbs y delays que suenan simultaneamente.
| Efecto | Parametros | Uso habitual |
|---|---|---|
Reverb | Mix, Duration y Decay | Habitaciones, cuevas, salas y espacios grandes. |
Delay / Echo | Mix, Delay Time y Feedback | Ecos y repeticiones. Feedback alto produce mas repeticiones. |
Filter | Low/High/Band Pass, Frequency, Resonance y Mix | Sonido bajo el agua, detras de paredes, radios o telefonos. |
Distortion | Amount y Mix | Motores, armas, impactos y sonido saturado. |
Stereo Pan | Pan de -1 a 1 y Mix | Coloca el sonido a la izquierda o derecha. |
Pitch | Pitch de 0.1 a 4 | Cambia velocidad y tono; 1 conserva el sonido original. |
API de Audio Effect
| Funcion | Uso |
|---|---|
AudioEffect.getAll(object) | Devuelve todos los efectos en el orden de la cadena. |
AudioEffect.get(object, index) | Devuelve un efecto por su indice, empezando en 0. |
AudioEffect.setEnabled(object, index, enabled) | Activa o desactiva un efecto. |
AudioEffect.setMix(object, index, mix) | Cambia la mezcla seca/procesada entre 0 y 1. |
AudioEffect.setReverb(object, index, options) | Configura duration, decay y mix. |
AudioEffect.setDelay(object, index, options) | Configura time, feedback y mix. |
AudioEffect.setFilter(object, index, options) | Configura type, frequency, resonance y mix. |
AudioEffect.setDistortion(object, index, amount, mix) | Configura la distorsion. |
AudioEffect.setPan(object, index, pan) | Configura panorama entre -1 y 1. |
AudioEffect.setPitch(object, index, pitch) | Configura pitch entre 0.1 y 4. |
Ejemplo: delay y reverb
export function start(object) {
// Primer Audio Effect: Delay.
AudioEffect.setDelay(object, 0, {
time: 0.25,
feedback: 0.35,
mix: 0.25
});
// Segundo Audio Effect: Reverb.
AudioEffect.setReverb(object, 1, {
duration: 1.8,
decay: 2.2,
mix: 0.4
});
AudioSource.play(object);
}
export function update(object) {
if (Input.getKeyDown("R")) {
AudioEffect.setEnabled(object, 1, false);
}
}
Empuje directo en objetos
Para aplicar fuerza no necesitas anadir Physics Body manualmente. Puedes llamar a estas funciones directamente desde el objeto y el motor creara el componente fisico automaticamente si hace falta.
| Funcion | Uso | Ejemplo |
|---|---|---|
object.addForwardForce(amount, axis) | Empuja el objeto hacia donde mira. axis indica que eje del sprite es el frente. | object.addForwardForce(500, "x") |
object.addForce(x, y) | Aplica fuerza en una direccion concreta. | object.addForce(0, -650) |
object.setGravity(enabled, scale) | Activa/desactiva gravedad. Crea Physics Body si falta. | object.setGravity(false) |
object.forward(axis) | Devuelve el vector frontal del objeto. | object.forward("-y") |
Anade Physics Body en el editor solo cuando quieras configurar masa, drag, rebote, friccion, gravedad o bloqueo de ejes visualmente.
Ejemplo: nave tipo Asteroids
Para una nave tipo Asteroids, desactiva la gravedad y aplica empuje en la direccion hacia la que mira la nave. Si quieres que no acelere infinitamente, anade Physics Body en el editor y sube un poco Drag.
export function start(object) {
object.setGravity(false);
}
export function update(object, deltaTime) {
if (Input.getKey("ArrowLeft")) {
object.rotation -= 180 * deltaTime;
}
if (Input.getKey("ArrowRight")) {
object.rotation += 180 * deltaTime;
}
if (Input.getKey("ArrowUp")) {
// Usa "x" si el sprite mira a la derecha por defecto.
// Usa "-y" si el sprite mira hacia arriba por defecto.
object.addForwardForce(520 * deltaTime, "x");
}
}
Bouncy Ball
Bouncy Ball convierte un objeto en una bola tipo Pong o Arkanoid. No necesita Physics Body: usa su propia velocidad interna y rebota contra los colliders de la escena.
Al anadir este componente, el motor activa Collision, desactiva Trigger y marca el objeto como no Static. Usa colliders en paredes, palas, bloques y limites para que la bola pueda rebotar.
| Propiedad | Uso |
|---|---|
Enabled | Activa o desactiva el componente. |
Start On Play | Si esta activo, la bola empieza a moverse al entrar en Play. |
Speed | Velocidad de la bola en pixeles por segundo. |
Angle | Direccion inicial de salida en grados. 0 derecha, 90 abajo, -90 arriba y 180 izquierda. |
Constant Speed | Mantiene la misma velocidad despues de cada rebote. |
API de Bouncy Ball
| Funcion | Uso | Ejemplo |
|---|---|---|
BouncyBall.get(object) | Devuelve el componente Bouncy Ball. | BouncyBall.get(ball) |
BouncyBall.setSpeed(object, speed) | Cambia la velocidad. | BouncyBall.setSpeed(ball, 420) |
BouncyBall.getSpeed(object) | Devuelve la velocidad actual. | BouncyBall.getSpeed(ball) |
BouncyBall.launch(object, angle, speed) | Lanza la bola con angulo y velocidad opcional. | BouncyBall.launch(ball, -45, 360) |
BouncyBall.stop(object) | Detiene la bola. | BouncyBall.stop(ball) |
object.setBouncySpeed(speed) | Version directa desde el objeto. | object.setBouncySpeed(500) |
object.launchBouncy(angle, speed) | Lanza la bola desde el propio objeto. | object.launchBouncy(-45, 360) |
Ejemplo: bola de Pong o Arkanoid
Crea una bola, anade el componente Bouncy Ball y activa Start On Play. Despues coloca colliders en las paredes, la pala y los bloques. Para Pong suele funcionar bien salir en diagonal. Para Arkanoid puedes relanzarla desde abajo cuando pierdes una vida.
// Script de la bola
export function start(object) {
// Sale hacia arriba y a la derecha.
object.launchBouncy(-45, 360);
}
export function update(object) {
// Relanzar la bola durante pruebas.
if (Input.getKeyDown("R")) {
object.launchBouncy(-45, 360);
}
// Subir velocidad poco a poco.
if (Input.getKeyDown("Space")) {
const speed = BouncyBall.getSpeed(object);
BouncyBall.setSpeed(object, speed + 40);
}
}
Ejemplo: pala de Arkanoid
La pala solo necesita moverse y tener Collision activo. La bola rebotara contra ella porque el componente Bouncy Ball gestiona su propia direccion despues del choque.
// Script de la pala
export function update(object, deltaTime) {
const speed = 420;
if (Input.getKey("A") || Input.getKey("ArrowLeft")) {
object.translate(-speed * deltaTime, 0);
}
if (Input.getKey("D") || Input.getKey("ArrowRight")) {
object.translate(speed * deltaTime, 0);
}
}
Waypoint Mover
Waypoint Mover mueve un objeto siguiendo una lista de puntos de mundo. Sirve para patrullas, plataformas, enemigos voladores, camaras, decoracion en movimiento o cualquier objeto que deba recorrer una ruta durante Play.
En el editor, al seleccionar el objeto, veras los puntos WP y las flechas de ruta. El componente solo mueve el objeto durante Play.
| Propiedad | Uso |
|---|---|
Speed | Velocidad en pixeles por segundo. |
Loop | Al llegar al final vuelve a empezar. |
Ping Pong | Recorre la ruta hacia delante y luego hacia atras. |
Random | Elige el siguiente waypoint al azar, evitando repetir el punto actual cuando hay mas de uno. |
Move Points With Object | Al mover el objeto en el editor, desplaza todos sus waypoints por la misma distancia. Es util para recolocar de una vez el objeto y su ruta completa. Funciona al arrastrar el objeto y al cambiar sus valores X/Y en el inspector; no modifica el movimiento durante Play. |
Rotate To Target | Rota el objeto mirando al waypoint al que se mueve. |
Flip X | Invierte la textura en X cuando el objeto se mueve hacia la izquierda y la restaura al moverse hacia la derecha. |
Flip Y | Invierte la textura en Y cuando el objeto se mueve hacia arriba y la restaura al moverse hacia abajo. |
Pause Min/Max | Pausa aleatoria general entre puntos. |
Waypoint P Min/P Max | Pausa aleatoria especifica para ese punto. |
Rotation Offset | Ajuste en grados si el sprite no mira hacia la derecha por defecto. |
Arrive Distance | Distancia a la que se considera que el objeto ya ha llegado. |
Para recolocar una patrulla completa, activa Move Points With Object antes de mover el
objeto. Desactivalo si quieres cambiar la posicion inicial del objeto sin desplazar la ruta.
API de Waypoint Mover
| Funcion | Uso | Ejemplo |
|---|---|---|
WaypointMover.get(object) | Devuelve el componente. | WaypointMover.get(enemy) |
WaypointMover.setSpeed(object, speed) | Cambia la velocidad. | WaypointMover.setSpeed(enemy, 180) |
WaypointMover.setLoop(object, loop, pingPong) | Cambia loop y opcionalmente ping pong. | WaypointMover.setLoop(enemy, true, true) |
WaypointMover.setRandom(object, random) | Activa o desactiva el modo aleatorio. | WaypointMover.setRandom(enemy, true) |
WaypointMover.setRotateToWaypoint(object, enabled, offset) | Activa rotacion hacia el objetivo. | WaypointMover.setRotateToWaypoint(enemy, true, 0) |
WaypointMover.setFlip(object, flipX, flipY) | Activa flip automatico segun direccion. | WaypointMover.setFlip(enemy, true, false) |
WaypointMover.setPause(object, min, max) | Cambia pausa aleatoria general. | WaypointMover.setPause(enemy, 0.2, 1) |
WaypointMover.setWaypoints(object, points) | Reemplaza la ruta completa. | WaypointMover.setWaypoints(enemy, points) |
WaypointMover.addWaypoint(object, x, y) | Anade un punto por codigo. | WaypointMover.addWaypoint(enemy, 400, 120) |
WaypointMover.clearWaypoints(object) | Borra la ruta. | WaypointMover.clearWaypoints(enemy) |
WaypointMover.goTo(object, index) | Fuerza el siguiente waypoint. | WaypointMover.goTo(enemy, 2) |
WaypointMover.pause(object, seconds) | Pausa temporalmente. | WaypointMover.pause(enemy, 2) |
WaypointMover.resume(object) | Reanuda el movimiento. | WaypointMover.resume(enemy) |
WaypointMover.reset(object) | Reinicia el ciclo. | WaypointMover.reset(enemy) |
object.setWaypointSpeed(speed) | Version directa desde el objeto. | object.setWaypointSpeed(200) |
object.goToWaypoint(index) | Version directa para cambiar objetivo. | object.goToWaypoint(1) |
Ejemplo: patrulla con ping pong
export function start(object) {
WaypointMover.setWaypoints(object, [
{ x: 100, y: 200, pauseMin: 0.2, pauseMax: 0.5 },
{ x: 360, y: 200, pauseMin: 0.2, pauseMax: 0.5 },
{ x: 360, y: 320, pauseMin: 0.8, pauseMax: 1.2 }
]);
WaypointMover.setLoop(object, true, true);
WaypointMover.setSpeed(object, 120);
}
Ejemplo: enemigo que elige puntos al azar
export function start(object) {
WaypointMover.setRandom(object, true);
WaypointMover.setPause(object, 0.3, 1.4);
WaypointMover.setRotateToWaypoint(object, true, 0);
}
Ejemplo: cambiar movimiento durante Play
export function update(object) {
if (Input.getKeyDown("1")) {
object.goToWaypoint(0);
}
if (Input.getKeyDown("2")) {
object.goToWaypoint(1);
}
if (Input.getKeyDown("Space")) {
object.pauseWaypointMover(1);
}
if (Input.getKeyDown("R")) {
object.resumeWaypointMover();
object.setWaypointSpeed(220);
}
}
Pathfinding Agent
Pathfinding Agent convierte un objeto en un agente capaz de buscar y seguir automaticamente una ruta alrededor de los objetos con colision. Es util para enemigos que persiguen al player, NPC, unidades de estrategia o personajes que deben llegar a un punto sin atravesar muros.
Anade el componente desde Add Component > Pathfinding Agent. Los colliders activos
forman los obstaculos; los objetos marcados como trigger no bloquean la ruta. Activa
Debug Path para ver la ruta en color magenta durante Play en el editor.
| Propiedad | Uso |
|---|---|
Target Mode | Busca el destino por tag, por nombre o usa unas coordenadas fijas. |
Target Tag / Name | Tag o nombre del objeto que el agente debe perseguir. |
Destination X/Y | Destino fijo cuando el modo seleccionado es Position. |
Speed | Velocidad de movimiento en pixeles por segundo. |
Cell Size | Tamano de cada celda de busqueda. Un valor pequeno da rutas mas precisas, pero necesita mas calculo. |
Padding | Margen adicional alrededor de los obstaculos para evitar rozarlos. |
Arrive Distance | Distancia a la que el destino se considera alcanzado. |
Repath Interval | Segundos entre recalculos mientras el objetivo se mueve. Bajarlo mejora la reaccion y aumenta el trabajo de CPU. |
Max Nodes | Limite de celdas que puede explorar una busqueda. |
Diagonal | Permite rutas y movimiento diagonal. |
Rotate To Target | Orienta el objeto en la direccion de movimiento. |
Flip X/Y | Invierte automaticamente el sprite segun la direccion. |
Rotation Offset | Corrige la orientacion si el sprite no mira hacia la derecha por defecto. |
API de Pathfinding Agent
| Funcion | Uso |
|---|---|
PathfindingAgent.get(object) | Devuelve el componente del objeto. |
PathfindingAgent.setEnabled(object, enabled) | Activa o desactiva el agente. |
PathfindingAgent.setTarget(object, target) | Hace que persiga un objeto concreto. |
PathfindingAgent.setDestination(object, x, y) | Cambia a modo Position y busca esas coordenadas. |
PathfindingAgent.setSpeed(object, speed) | Cambia la velocidad. |
PathfindingAgent.pause(object) | Pausa el movimiento sin borrar el destino. |
PathfindingAgent.resume(object) | Reanuda y recalcula la ruta. |
PathfindingAgent.stop(object) | Detiene el agente y borra su ruta actual. |
PathfindingAgent.recalculate(object) | Fuerza un nuevo calculo de ruta. |
PathfindingAgent.hasPath(object) | Indica si existe una ruta activa. |
PathfindingAgent.hasArrived(object) | Indica si ha alcanzado el destino. |
Ejemplo: perseguir al player
export function start(object) {
const player = FindByTag("Player");
PathfindingAgent.setTarget(object, player);
PathfindingAgent.setSpeed(object, 100);
}
Ejemplo: enviar un objeto a una posicion
export function update(object) {
if (Input.getKeyDown("Space")) {
PathfindingAgent.setDestination(object, 640, 320);
}
if (PathfindingAgent.hasArrived(object)) {
// El objeto ya ha llegado.
}
}
Waypoint Mover sigue una ruta dibujada manualmente. Pathfinding Agent calcula la ruta y la modifica para rodear obstaculos.
Look At Target
Look At Target mantiene un objeto orientado hacia otro. Esta pensado para torretas, canones, focos, ojos, enemigos y cualquier objeto que deba seguir visualmente a un objetivo sin cambiar su posicion.
| Propiedad | Uso |
|---|---|
Target Mode | Localiza el objetivo por tag o por nombre. |
Target Tag / Name | Tag o nombre del objeto al que debe mirar. |
Turn Speed | Velocidad maxima de giro en grados por segundo. Con 0 gira instantaneamente. |
Reaction Delay | Tiempo en segundos entre actualizaciones de la direccion objetivo. Con 0 sigue al target en cada frame. |
Original Direction | Direccion hacia la que apunta el dibujo sin ninguna rotacion: derecha, abajo, izquierda, arriba o personalizada. |
Original Angle | Angulo personalizado de la orientacion original del sprite. Derecha es 0°, abajo 90°, izquierda 180° y arriba -90°. |
Ejemplo: si el canon de la imagen apunta hacia arriba, selecciona Up (-90°). El
componente aplicara automaticamente la correccion necesaria para que esa punta mire al target.
API de Look At Target
| Funcion | Uso |
|---|---|
LookAtTarget.get(object) | Devuelve el componente. |
LookAtTarget.setEnabled(object, enabled) | Activa o desactiva la orientacion. |
LookAtTarget.setTarget(object, target) | Asigna directamente otro objeto como objetivo. |
LookAtTarget.setTarget(object, "Enemy", "tag") | Busca el objetivo por tag. |
LookAtTarget.setTurnSpeed(object, speed) | Cambia la velocidad de giro en grados por segundo. |
LookAtTarget.setReactionDelay(object, seconds) | Cambia el retardo de reaccion. |
LookAtTarget.setOriginalAngle(object, angle) | Indica la orientacion original del sprite. |
LookAtTarget.refresh(object) | Fuerza una actualizacion inmediata de la direccion. |
Ejemplo: torreta que sigue al player
export function start(object) {
LookAtTarget.setTarget(object, "Player", "tag");
LookAtTarget.setTurnSpeed(object, 120);
LookAtTarget.setReactionDelay(object, 0.1);
// La imagen original del canon apunta hacia arriba.
LookAtTarget.setOriginalAngle(object, -90);
}
Physics Body
Physics Body anade gravedad, velocidad y respuesta fisica sencilla a un objeto. Usalo para cajas, enemigos, proyectiles, objetos que caen o elementos que quieras mover con fuerzas. Para personajes jugables de plataformas sigue siendo mejor usar Character Controller.
El componente solo se actualiza durante Play. Al anadirlo, el objeto activa automaticamente
Collision y deja de ser Static, porque necesita poder moverse.
Los objetos con Body Type: Dynamic pueden ser empujados lateralmente por el player,
por otro Character Controller o por otro Physics Body. Cuanta mas
Mass tenga el objeto, mas costara moverlo.
| Propiedad | Uso |
|---|---|
Body Type | Dynamic recibe gravedad y colisiones. Kinematic se mueve por velocidad/script, pero no recibe gravedad. |
Use Gravity | Activa o desactiva la gravedad del componente. |
Gravity Scale | Multiplica la gravedad del motor. 1 es normal, 0.5 cae mas lento y 2 cae mas rapido. |
Mass | Masa usada por Physics.addForce y por los empujes. Mas masa significa que la misma fuerza o empuje cambia menos la velocidad. |
Velocity X/Y | Velocidad actual en pixeles por segundo. |
Drag | Freno gradual aplicado a la velocidad. |
Max Fall Speed | Limite de velocidad al caer. |
Freeze X/Y | Bloquea el movimiento fisico en un eje. |
Bounce | Rebote al chocar. 0 no rebota; valores mayores devuelven parte de la velocidad. |
Friction | Reduce velocidad horizontal al tocar suelo. |
API de Physics
| Funcion | Uso | Ejemplo |
|---|---|---|
Physics.get(object) | Devuelve el componente Physics Body. | Physics.get(object) |
Physics.has(object) | Indica si el objeto tiene Physics Body. | Physics.has(box) |
Physics.getVelocity(object) | Devuelve { x, y }. | Physics.getVelocity(object).y |
Physics.setVelocity(object, x, y) | Cambia la velocidad directamente. | Physics.setVelocity(object, 200, -350) |
Physics.addVelocity(object, x, y) | Suma velocidad a la actual. | Physics.addVelocity(object, 0, -120) |
Physics.addForce(object, x, y) | Aplica una fuerza instantanea teniendo en cuenta la masa. | Physics.addForce(object, 0, -500) |
Physics.addForwardForce(object, amount, axis) | Aplica fuerza hacia donde mira el objeto. axis indica que eje del sprite es el frente. | Physics.addForwardForce(ship, 420, "x") |
Physics.forward(object, axis) | Devuelve el vector de direccion frontal del objeto. | Physics.forward(ship, "-y") |
Physics.stop(object) | Pone velocidad X/Y a cero. | Physics.stop(object) |
Physics.setGravity(object, enabled, scale) | Activa/desactiva gravedad y opcionalmente cambia escala. | Physics.setGravity(object, true, 1.5) |
Physics.setKinematic(object, kinematic) | Cambia entre kinematic y dynamic. | Physics.setKinematic(object, true) |
Physics.setEnabled(object, enabled) | Activa o desactiva el componente. | Physics.setEnabled(object, false) |
Physics.isGrounded(object) | Indica si esta tocando suelo. | Physics.isGrounded(object) |
export function start(object) {
Physics.setVelocity(object, 120, -300);
}
export function update(object) {
if (Input.getKeyDown("Space") && Physics.isGrounded(object)) {
Physics.addForce(object, 0, -650);
}
if (object.isOutsideCamera(100)) {
Destroy(object);
}
}
Parallax
Parallax desplaza la textura del objeto usando la camara de Play o un objeto target. Para fondos, nubes y capas de escenario, el parallax usa la camara de Play cuando no hay target asignado. Solo se movera si la camara de Play tiene Follow Player activo.
En el editor el efecto permanece estatico. El movimiento de Parallax solo se ejecuta durante Play. El objeto mantiene su posicion original y su tamano en pantalla; el componente compensa la camara y solo desplaza la textura. El target manual queda para casos especiales donde quieras que la capa responda a un objeto concreto en vez de a la camara.
| Propiedad | Uso |
|---|---|
Target | Objeto que controla el desplazamiento de la textura. |
Target | Objeto opcional que controla el parallax. Si esta vacio se usa la camara de Play. |
Speed X/Y | Multiplicador de desplazamiento por eje. 1 es una velocidad normal; puede ser negativo. |
Smooth X/Y | Suavizado por eje. 0 es inmediato; valores altos suavizan mas. |
Margin X/Y | Zona muerta por eje antes de mover la textura, util para camaras tipo Mario. |
Repeat X/Y | Repite la textura horizontal o verticalmente. |
Lock X/Y | Bloquea el movimiento de la textura en ese eje. |
Enabled | Activa o desactiva el componente. |
API de Parallax
| Funcion | Uso | Ejemplo |
|---|---|---|
Parallax.get(object) | Devuelve el componente Parallax activo. | Parallax.get(bg) |
Parallax.setTarget(object, target) | Cambia el objeto target. | Parallax.setTarget(bg, player) |
Parallax.setSpeed(object, x, y) | Cambia velocidad X/Y. | Parallax.setSpeed(bg, 1, 0) |
Parallax.setSmooth(object, x, y) | Cambia suavizado X/Y. | Parallax.setSmooth(bg, 0.85, 0) |
Parallax.setMargin(object, x, y) | Cambia margen X/Y en pixeles de mundo. | Parallax.setMargin(bg, 120, 0) |
Parallax.setRepeat(object, x, y) | Activa repeticion X/Y. | Parallax.setRepeat(bg, true, false) |
Parallax.setLock(object, x, y) | Bloquea ejes. | Parallax.setLock(bg, false, true) |
Parallax.setEnabled(object, enabled) | Activa o desactiva. | Parallax.setEnabled(bg, true) |
export function start(object) {
const player = FindByName("Player");
Parallax.setTarget(object, player);
Parallax.setSpeed(object, 1, 0);
Parallax.setSmooth(object, 0.85, 0);
Parallax.setMargin(object, 120, 0);
Parallax.setRepeat(object, true, false);
Parallax.setLock(object, false, true);
}
Character Controller
Character Controller mueve un personaje 2D sin tener que escribir todo el codigo de movimiento a mano. Sirve para juegos de plataformas y movimiento libre tipo top-down.
El componente solo se ejecuta durante Play. En el editor no mueve el objeto. En el Inspector se muestra una tarjeta resumida; pulsa Edit para abrir la ventana completa de configuracion en el centro de la pantalla. La ventana cambia segun el modo elegido y oculta las opciones que no se usan en ese tipo de controlador.
Parametros comunes
| Parametro | Tipo | Explicacion |
|---|---|---|
Mode | Selector | Elige el tipo de controlador: Platformer para plataformas con gravedad o Top Down para movimiento libre en vista superior. |
Analog Movement | Selector | Progressive conserva la intensidad del stick: una inclinacion pequeña mueve mas despacio. Fixed convierte cualquier inclinacion que supere la zona muerta en movimiento a velocidad completa. |
Gamepad Dead Zone | Numero 0-0.95 | Ignora pequeñas desviaciones del stick para evitar movimiento involuntario. El valor predeterminado es 0.12; normalmente se recomienda entre 0.10 y 0.20. |
Enabled | Check | Activa o desactiva el componente sin quitarlo del objeto. |
Use Collisions | Check | Usa el sistema de colisiones del motor. En Platformer sirve para suelo, paredes, plataformas y escaleras. En Top Down mantiene el controlador preparado para contactos de mundo. |
Apply Animations | Check | Cambia automaticamente la animacion del objeto cuando cambia el estado del controlador. |
Flip X Direction | Check | Voltea la textura en X al cambiar la direccion horizontal. Es lo habitual para personajes que miran izquierda/derecha. |
Flip Y Direction | Check | Voltea la textura en Y al cambiar la direccion vertical. Solo suele usarse en juegos top-down o casos especiales. |
Horizontal | Check | Permite o bloquea el movimiento en el eje X. |
Vertical | Check | Permite o bloquea el movimiento en el eje Y. En plataformas normalmente se deja activo para salto/gravedad; en top-down controla subir y bajar. |
Move Speed | Numero | Velocidad base del personaje en pixeles por segundo. |
Death State | Check | Permite usar el estado de muerte desde script con CharacterController.setDead(object, true). |
Tipo Platformer
Usa Platformer para juegos laterales con gravedad: plataformas, saltos, suelo, rampas, escaleras y plataformas moviles. El controlador aplica movimiento horizontal, gravedad, salto y deteccion de suelo durante Play.
| Parametro | Tipo | Explicacion |
|---|---|---|
Run | Check | Activa una velocidad de carrera opcional mientras se mantiene pulsada la tecla configurada. |
Run Speed | Numero | Velocidad usada al correr. Debe ser mayor que Move Speed si quieres que se note la carrera. |
Run Key | Texto | Tecla para correr. Por defecto suele usarse Shift. |
Run Button | Selector | Boton del mando que se mantiene pulsado para correr. El valor predeterminado para Xbox es X. |
Jump | Check | Permite saltar. Si esta desactivado, el personaje no responde a la tecla de salto. |
Jump Key | Texto | Tecla de salto. Por defecto suele usarse Space. |
Jump Button | Selector | Boton del mando para saltar. El valor predeterminado para Xbox es A. |
Jump Force | Numero | Fuerza inicial del salto. Valores mas altos hacen que el personaje suba mas rapido y mas alto. |
Gravity | Numero | Fuerza que empuja al personaje hacia abajo. Valores altos producen caidas mas rapidas. |
Max Fall | Numero | Velocidad maxima de caida. Evita que el personaje acelere indefinidamente. |
Double Jump | Check | Permite saltar de nuevo en el aire. |
Max Jumps | Numero | Total de saltos permitidos antes de volver a tocar suelo. Para doble salto normalmente es 2. |
Crouch | Check | Activa estado de agacharse. |
Crouch Key | Texto | Tecla para agacharse. Por defecto suele usarse S. |
Crouch Button | Selector | Boton del mando que se mantiene pulsado para agacharse. El valor predeterminado para Xbox es B. |
Crouch Speed | Numero 0-1 | Multiplicador de velocidad al agacharse. 0.5 significa moverse a la mitad de velocidad. |
Use Ladders | Check | Permite usar objetos con componente Ladder. Al tocar una escalera el personaje pierde la gravedad y puede subir o bajar con el input. |
Ladder Speed | Numero | Velocidad al moverse por una escalera. |
Para que las escaleras funcionen, el objeto escalera debe tener el componente Ladder. El personaje puede saltar desde la escalera para salir de ella.
Tipo Top Down
Usa Top Down para juegos vistos desde arriba o con movimiento libre en X/Y: aventuras, shooters, RPG de accion o juegos donde el personaje no tiene gravedad ni salto. El controlador normaliza la diagonal para que moverse en diagonal no sea mas rapido.
| Parametro | Tipo | Explicacion |
|---|---|---|
Move Speed | Numero | Velocidad base para moverse en cualquier direccion. |
Run | Check | Activa carrera opcional tambien en top-down. |
Run Speed | Numero | Velocidad usada mientras la tecla de carrera esta pulsada. |
Run Key | Texto | Tecla para correr. |
Run Button | Selector | Boton del mando para correr. Por defecto, X. |
Crouch | Check | Activa un estado lento o de sigilo si tu juego lo necesita. |
Crouch Key | Texto | Tecla para activar el estado de agachado/sigilo. |
Crouch Button | Selector | Boton del mando para activar el estado de agachado o sigilo. Por defecto, B. |
Crouch Speed | Numero 0-1 | Multiplicador de velocidad durante el estado crouch. |
Horizontal | Check | Permite moverse izquierda/derecha. |
Vertical | Check | Permite moverse arriba/abajo. |
Flip X Direction | Check | Util para personajes que miran izquierda/derecha segun la direccion horizontal. |
Flip Y Direction | Check | Util para sprites que deban invertirse al mirar arriba/abajo. |
Cuatro ataques
Los modos Platformer y Top Down disponen de cuatro ataques independientes. Cada slot permite elegir tecla, boton de mando, duracion, animacion y sonido. Effect Prefab es opcional: puede ser un proyectil, una zona trigger invisible o cualquier efecto creado como prefab.
| Parametro | Uso |
|---|---|
Attack 1..4 | Activa individualmente cada ataque. |
Animation / Sound / Volume | La duracion del ataque se calcula automaticamente con los frames y FPS de la animacion. Se reproduce una sola vez aunque el clip tenga Loop. |
Effect Prefab | Prefab opcional. Usa None para controlar el ataque solo por codigo. |
Prefab Offset X/Y | Posicion local desde el centro: X es delante/detras e Y es el desplazamiento lateral. |
Prefab Rotation | Giro adicional del prefab. |
Follow character direction | Refleja el offset en Platformer y sigue la ultima direccion en Top Down. |
Allow movement while attacking | Permite seguir andando o corriendo durante el ataque. Si se desactiva, bloquea el desplazamiento pero conserva gravedad y colisiones. |
Los ataques arrancan con la pulsacion inicial. Las acciones tactiles son Attack/Attack1, Attack2, Attack3 y Attack4.
Animaciones y sonidos por estado
| Modo | Estados disponibles | Uso |
|---|---|---|
Platformer | Idle, Move, Run, Jump, Fall, Crouch, Death, Ladder Idle, Ladder Walk | Permite asignar animacion y sonido a cada estado de plataformas, incluyendo escalera. |
Top Down | Idle, movimiento en 8 direcciones, Run, Crouch y Death | Las ocho animaciones de caminar distinguen arriba, abajo, izquierda, derecha y las cuatro diagonales. Si una queda vacia se usa Move Fallback. Los cuatro ataques se configuran en su propia seccion. |
| Parametro | Explicacion |
|---|---|
* Anim | Animacion asignada a un estado. Por ejemplo, Run Anim se reproduce al correr. |
* Sound | Sonido que se reproduce al entrar en ese estado. Los sonidos no heredan de otros estados para evitar dobles disparos. |
Vol | Volumen independiente del sonido de ese estado, entre 0 y 1. |
Loop | Hace que el sonido del estado se repita hasta cambiar de estado o salir de Play. |
Los sonidos del Character Controller usan los sonidos del panel Sounds. Se cargan al iniciar el proyecto y se mantienen en memoria; el componente solo elige cual reproducir al cambiar de estado. Si Mute in Play esta activo, estos sonidos tambien se silencian.
API de CharacterController
| Funcion | Uso | Ejemplo |
|---|---|---|
CharacterController.get(object) | Devuelve el componente del objeto. | CharacterController.get(object) |
CharacterController.isGrounded(object) | Indica si el personaje esta tocando suelo. | CharacterController.isGrounded(object) |
CharacterController.getVelocity(object) | Devuelve { x, y } con la velocidad interna. | CharacterController.getVelocity(object) |
CharacterController.setVelocity(object, x, y) | Cambia la velocidad interna. | CharacterController.setVelocity(object, 0, -300) |
CharacterController.setDead(object, dead) | Activa o desactiva el estado de muerte. | CharacterController.setDead(object, true) |
CharacterController.isDead(object) | Consulta si esta en estado de muerte. | CharacterController.isDead(object) |
CharacterController.resetJumps(object) | Restablece los saltos disponibles. | CharacterController.resetJumps(object) |
CharacterController.setEnabled(object, enabled) | Activa o desactiva el componente. | CharacterController.setEnabled(object, false) |
CharacterController.onAttack(object, callback) | Ejecuta el callback al comenzar cualquiera de los cuatro ataques, tenga prefab o no. | CharacterController.onAttack(object, hit) |
CharacterController.offAttack(object, callback?) | Quita un callback concreto; sin callback quita todos los del objeto. | CharacterController.offAttack(object, hit) |
export function update(object) {
if (Input.getKeyDown("K")) {
CharacterController.setDead(object, true);
}
if (CharacterController.isGrounded(object)) {
debug("En suelo");
}
}
function receiveAttack(attack) {
// attack.index: 1..4
// attack.x / attack.y: configured effect origin
// attack.direction: normalized facing direction
if (attack.index === 2) {
Debug.log(`Ataque especial en ${attack.x}, ${attack.y}`);
}
}
export function start(object) {
CharacterController.onAttack(object, receiveAttack);
}
18. Input
Input permite leer teclado, ratón, gamepad y touch desde scripts. La API funciona en
Play. En modo editor no controla la escena ni
devuelve pulsaciones para no interferir con las herramientas del editor.
Fuera de Play, Input devuelve valores neutros: false en botones/teclas,
0 en ejes y posiciones, y null en getTouch.
Teclado
| Funcion | Uso | Ejemplo |
|---|---|---|
Input.getKey(key) | Mientras una tecla esta pulsada. | Input.getKey("A") |
Input.getKeyDown(key) | Solo el frame en que se pulsa. | Input.getKeyDown("Space") |
Input.getKeyUp(key) | Solo el frame en que se suelta. | Input.getKeyUp("Escape") |
Input.anyKey() | Alguna tecla esta pulsada. | Input.anyKey() |
Input.anyKeyDown() | Alguna tecla se acaba de pulsar. | Input.anyKeyDown() |
Puedes usar letras como "A", teclas especiales como "Escape",
"Enter", "Shift", "Control", "Alt",
"Space", flechas como "ArrowLeft" y tambien codigos de
KeyboardEvent.code como "KeyA".
Teclas habituales soportadas: "A", "B", "Escape",
"Enter", "Shift", "Control", "Alt",
"ArrowLeft", "ArrowRight", "ArrowUp",
"ArrowDown" y "Space".
export function update(object, deltaTime) {
if (Input.getKey("D")) {
object.translate(160 * deltaTime, 0);
}
if (Input.getKeyDown("Space")) {
debug("Salto");
}
}
Raton
| Propiedad o funcion | Uso |
|---|---|
Input.mouseX, Input.mouseY | Posicion del raton en pantalla/canvas. |
Input.mouseWorldX, Input.mouseWorldY | Posicion del raton en coordenadas de mundo. |
Input.mouseDeltaX, Input.mouseDeltaY | Movimiento del raton durante el frame. |
Input.mouseWheel | Movimiento de la rueda durante el frame. |
Input.getMouseButton(0) | Boton izquierdo pulsado. |
Input.getMouseButtonDown(0) | Boton izquierdo pulsado este frame. |
Input.getMouseButtonUp(0) | Boton izquierdo soltado este frame. |
Input.hideCursor() | Oculta el puntero del raton durante Play. |
Input.showCursor() | Vuelve a mostrar el puntero del raton. |
Input.setCursorVisible(false) | Muestra u oculta el puntero con un booleano. |
Input.isCursorVisible() | Devuelve si el puntero esta visible. |
Botones: 0 izquierdo, 1 central, 2 derecho.
export function update(object, deltaTime) {
if (Input.getMouseButtonDown(0)) {
object.x = Input.mouseWorldX;
object.y = Input.mouseWorldY;
}
}
export function start(object) {
Input.hideCursor();
}
export function update(object, deltaTime) {
if (Input.getKeyDown("Escape")) {
Input.showCursor();
}
}
Gamepad
Input usa la Gamepad API del navegador y normaliza mandos Xbox, PlayStation, Nintendo,
USB, Bluetooth y genericos. Puede haber varios mandos conectados.
| Funcion | Uso | Ejemplo |
|---|---|---|
Input.gamepadCount | Mandos conectados. | Input.gamepadCount |
Input.getButton(button) | Boton pulsado. | Input.getButton("A") |
Input.getButtonDown(button) | Boton pulsado este frame. | Input.getButtonDown("Cross") |
Input.getButtonUp(button) | Boton soltado este frame. | Input.getButtonUp("Start") |
Input.getAxis(axis, deadZone?, gamepadIndex?) | Valor de eje entre -1 y 1. Permite ajustar la zona muerta y elegir un mando concreto por su indice, empezando en 0. | Input.getAxis("LeftStickY", 0.12, 1) |
await Input.vibrate(ms, fuerte, suave, indice) | Activa la vibracion del mando y devuelve si esta soportada. | await Input.vibrate(250, 1, 0.5, 0) |
Input.stopVibration(indice) | Detiene la vibracion del mando. | Input.stopVibration(0) |
Botones soportados: A, B, X, Y,
Cross, Circle, Square, Triangle,
L1, R1, L2, R2, Start,
Select, Back, Options, Share,
LeftStick, RightStick, DPadUp, DPadDown,
DPadLeft y DPadRight.
Ejes soportados: LeftStickX, LeftStickY, RightStickX,
RightStickY, LeftTrigger y RightTrigger.
Si hay varios mandos, puedes indicar el indice como segundo parametro:
Input.getButton("A", 0). Si no indicas indice, se acepta el primer mando que tenga ese
boton pulsado.
La vibracion depende del mando, navegador y sistema operativo. La intensidad fuerte y suave usa
valores entre 0 y 1. Si el dispositivo no dispone de actuador, la funcion
devuelve false sin detener el juego.
Activar y detener la vibracion
export async function update(object) {
if (Input.getButtonDown("A")) {
const supported = await Input.vibrate(
300, // duracion en milisegundos
1, // motor fuerte: 0 a 1
0.4, // motor suave: 0 a 1
0 // indice del mando
);
if (!supported) {
debug("Este mando no soporta vibracion");
}
}
if (Input.getButtonDown("B")) {
Input.stopVibration(0);
}
}
export function onPlayerHit() {
// Golpe corto.
Input.vibrate(120, 0.8, 0.3);
}
export function onExplosionStart() {
// Empieza una vibracion larga.
Input.vibrate(2000, 1, 1);
}
export function onExplosionEnd() {
// La detiene antes de que terminen los 2000 ms.
Input.stopVibration();
}
Ejes de movimiento
Horizontal y Vertical combinan teclado y gamepad.
Por defecto: A/D, flechas izquierda/derecha, W/S y flechas arriba/abajo.
Movimiento vertical para Pong
export function update(object, deltaTime) {
const vertical = Input.getAxis("Vertical");
object.translate(0, -vertical * speed * deltaTime);
}
Este ejemplo controla un solo eje con W/S, las flechas arriba/abajo y el stick izquierdo.
La intensidad del stick se conserva, por lo que una inclinacion pequeña produce un movimiento mas lento.
export function update(object, deltaTime) {
const move = Input.getMovementVector();
object.translate(
move.x * 180 * deltaTime,
-move.y * 180 * deltaTime
);
}
Input.getMovementVector() combina Horizontal y Vertical y
normaliza la diagonal. Asi no se mueve mas rapido al pulsar dos direcciones. En este motor
Vertical devuelve positivo hacia arriba; por eso el ejemplo usa -move.y.
El teclado y el mando funcionan con la misma API tanto en Play como en el juego publicado en GameCrom. Si actualizas los controles o el motor, publica una nueva versión para que el juego use los cambios.
Touch
| Funcion | Uso |
|---|---|
Input.touchCount | Numero de dedos tocando la pantalla. |
Input.getTouch(index) | Devuelve { id, x, y, worldX, worldY } o null. |
18.1. Controles moviles
GameCrom incluye controles tactiles visuales para que los juegos Web puedan jugarse desde moviles y
tabletas. Los controles forman parte de Canvas UI, admiten varias pulsaciones a la vez
y alimentan la misma API Input que el teclado y el mando. No necesitas crear una version
diferente del movimiento para movil.
Crear controles tactiles
- Crea o selecciona un UI Canvas.
- Abre Add GameObject > Mobile Controls.
- Anade Touch Joystick, Touch D-Pad o Touch Button.
- Coloca el joystick o la cruceta en la parte inferior izquierda y los botones en la derecha.
- Configura sus ejes o su accion desde el Inspector.
- Opcionalmente, asigna una imagen de Textures a cada control.
- Pruebalo en Play con el raton o genera un build nuevo para probar multitouch en el dispositivo.
| Control | Funcion | Configuracion habitual |
|---|---|---|
Touch Joystick | Movimiento analogico en cualquier direccion. Devuelve valores entre -1 y 1. | Horizontal y Vertical. |
Touch D-Pad | Cruceta digital. Cada direccion devuelve -1, 0 o 1. | Horizontal y Vertical. |
Touch Button | Boton mantenido, recien pulsado o recien soltado. | Acciones como Jump, Run, Crouch, Attack o Pause. |
Propiedades del Inspector
| Propiedad | Uso |
|---|---|
Horizontal Axis | Nombre del eje horizontal que recibe el joystick o la cruceta. Normalmente Horizontal. |
Vertical Axis | Nombre del eje vertical. Normalmente Vertical; positivo significa arriba. |
Action | Nombre de la accion enviada por un Touch Button. Distingue mayusculas y minusculas. |
Image | Imagen normal del Touch Button, imagen completa del D-Pad o imagen de base del joystick. |
Pressed Image | Imagen que muestra un Touch Button mientras permanece pulsado. Si se deja en None, conserva la imagen normal. |
Inner Image | Imagen del circulo interior movil del Touch Joystick. Se recorta automaticamente con forma circular. |
Inner Opacity | Opacidad independiente del circulo interior del joystick, entre 0 y 1. |
Visual Style | Aspecto del D-Pad: 4 Arrows, 8 Arrows o Classic Cross. Solo cambia el dibujo; los tres estilos conservan el mismo funcionamiento y permiten diagonales. |
Joystick Mode | Fixed mantiene el joystick en su posicion. Floating in Area lo oculta hasta tocar la zona y lo centra bajo el dedo. |
Activation Area | Zona que puede iniciar un joystick flotante: Left Half, Right Half, Full Screen o Custom Area. |
Always Visible | Si esta marcado, el joystick se ve en reposo y se desplaza al punto tocado. Si no esta marcado, permanece oculto y solo aparece mientras un dedo mantiene pulsada su zona. |
Area Position % | Posicion X/Y del area personalizada como porcentaje de la pantalla del juego. |
Area Size % | Anchura y altura del area personalizada como porcentaje. Por ejemplo, X 0, Y 0, W 50, H 100 ocupa la mitad izquierda. |
Dead Zone | Ignora movimientos pequenos cerca del centro del joystick. El valor recomendado inicial es 0.12. |
Sensitivity | Multiplica la respuesta del joystick antes de limitarla al intervalo de -1 a 1. |
Touch devices only | Oculta el control en equipos sin pantalla tactil. Desactivalo mientras quieras probarlo con raton en Play. |
Background, Border, Opacity | Personalizan el aspecto visual. Una opacidad moderada evita tapar el juego. |
Anchor, posicion y tamano | Mantienen cada control unido a una esquina y permiten adaptarlo a diferentes pantallas. |
Leer movimiento y acciones
En modo Floating in Area no hace falta acertar sobre un control pequeno: el primer toque
dentro de la zona crea el centro del joystick en ese punto. El dedo puede desplazarse desde ese centro
y, al soltarlo, el joystick vuelve a ocultarse. Los botones tactiles colocados sobre la zona tienen
prioridad, por lo que siguen funcionando aunque las areas se solapen.
Al seleccionar un Touch Joystick flotante en el editor, su zona de activacion aparece marcada con lineas discontinuas y un relleno azul tenue. La guia solo pertenece al editor y no se dibuja en el juego.
export function update(object, deltaTime) {
// Teclado, mando, joystick tactil y cruceta usan los mismos ejes.
const x = Input.getAxis("Horizontal");
const y = Input.getAxis("Vertical");
object.translate(x * 220 * deltaTime, -y * 220 * deltaTime);
// Verdadero mientras el boton tactil permanezca pulsado.
if (Input.isActionPressed("Attack")) {
// Ataque continuo.
}
// Solo durante el frame inicial de la pulsacion.
if (Input.isActionDown("Jump")) {
// Saltar una vez.
}
// Solo durante el frame en que se suelta.
if (Input.isActionUp("Pause")) {
// Abrir o cerrar el menu de pausa.
}
}
| Funcion | Resultado |
|---|---|
Input.isActionPressed(name) | true mientras al menos un boton de esa accion siga pulsado. |
Input.isActionDown(name) | true solamente en el primer frame de la pulsacion. |
Input.isActionUp(name) | true solamente en el frame de liberacion. |
Input.isTouchDevice() | Indica si el dispositivo informa de soporte tactil. |
Character Controller
El Character Controller usa automaticamente los ejes Horizontal y
Vertical. Tambien reconoce las acciones tactiles Jump, Run,
Crouch y Attack. Para un personaje basico basta con crear un joystick y los
botones de accion necesarios; no hace falta escribir movimiento adicional.
Multitouch en GameCrom
Cada dedo mantiene su propio control: el jugador puede mover el joystick y pulsar varios botones al mismo tiempo. Funciona en el juego publicado en GameCrom cuando el dispositivo dispone de entrada táctil. Después de modificar los controles o actualizar el motor, publica una nueva versión.
Los controles visuales y Input.getTouch(index) resuelven casos distintos. Usa los controles
visuales para movimiento y acciones habituales. Usa getTouch cuando necesites posiciones de
dedos, dibujar con el dedo, seleccionar objetos del mundo o implementar un gesto personalizado.
19. Colisiones 2D
El motor incluye colisiones 2D basadas en SAT. Para que un objeto participe en colisiones, activa Collision en el bloque Collider 2D del Inspector. Si activas Trigger, el objeto detecta contactos pero no empuja ni bloquea a otros objetos.
| Opcion | Que hace |
|---|---|
Collision | Incluye el objeto en el sistema de colisiones durante Play. |
Trigger | Detecta contacto sin resolver fisicamente la colision. |
One Way Platform | Permite atravesar la plataforma saltando desde abajo y caer encima desde arriba. |
Shape | Forma del collider. Los objetos Square usan Box por defecto; los objetos Circle usan Circle y tambien pueden usar Capsule. |
Offset | Desplaza el collider respecto al centro del objeto sin mover el render. |
Size | Ancho y alto del collider para Box y Capsule. |
Radius | Radio del collider cuando la forma es Circle. |
Static | El objeto no se mueve al resolver colisiones. Sirve para suelos, paredes y plataformas. |
Las colisiones funcionan con rotacion, escala y jerarquias. El collider se ve en azul en la escena cuando el objeto esta seleccionado y Collision esta activo. Solo se actualizan en Play.
Componentes de escenario
| Componente | Uso |
|---|---|
Ladder | Convierte el objeto en una zona de escalera. Al anadirlo activa Collision y Trigger. El Character Controller suspende la gravedad mientras la esta tocando y puede saltar desde ella. |
Moving Platform | Mueve el objeto entre su posicion inicial y un offset X/Y. Al seleccionar el objeto en editor se dibuja una referencia visual con START, END, flecha de recorrido y silueta de destino sin mover la plataforma. |
Conveyor Belt | Convierte un collider solido en una cinta transportadora que desplaza hacia la izquierda o derecha los personajes y cuerpos fisicos apoyados encima. |
Texture Scroller | Anima el offset X/Y de la textura del objeto durante Play, con velocidad configurable y control desde scripts. |
Conveyor Belt
Conveyor Belt crea el efecto clasico de cinta transportadora. Mientras un objeto compatible esta apoyado encima, la cinta lo desplaza horizontalmente a la velocidad configurada. Funciona tanto en el Play del editor como en el juego exportado.
Para usarlo, selecciona el suelo o plataforma, pulsa
Add Component > Conveyor Belt y ajusta sus propiedades. Al anadirlo, el editor activa
automaticamente Collision y desactiva Trigger en la cinta.
| Propiedad | Uso |
|---|---|
Enabled | Activa o desactiva el movimiento de la cinta. |
Direction | Elige si la cinta arrastra hacia Left o Right. |
Speed | Velocidad horizontal en pixeles por segundo. |
Affect Characters | Arrastra objetos que tengan un componente Character Controller activo. |
Affect Physics Bodies | Arrastra objetos que tengan un componente Physics Body activo. |
El objeto transportado debe estar apoyado sobre la parte superior de la cinta y tener
Character Controller o Physics Body, segun los filtros activados. La cinta no
desplaza objetos decorativos sin uno de esos componentes.
API de Conveyor Belt
| Funcion | Uso | Ejemplo |
|---|---|---|
ConveyorBelt.get(object) | Devuelve el componente. | ConveyorBelt.get(object) |
ConveyorBelt.setEnabled(object, enabled) | Activa o detiene la cinta. | ConveyorBelt.setEnabled(object, false) |
ConveyorBelt.setSpeed(object, speed) | Cambia la velocidad en pixeles por segundo. | ConveyorBelt.setSpeed(object, 160) |
ConveyorBelt.setDirection(object, direction) | Cambia la direccion a "left" o "right". | ConveyorBelt.setDirection(object, "left") |
ConveyorBelt.setAffects(object, characters, physicsBodies) | Elige los tipos de objeto que transporta. | ConveyorBelt.setAffects(object, true, false) |
Texture Scroller
Texture Scroller modifica continuamente Texture Offset X y
Texture Offset Y durante Play. Sirve para cintas animadas, agua, lava, nubes, fondos en
movimiento o cualquier textura repetida. La textura debe tener un tiling adecuado para que el
desplazamiento sea visible de forma continua.
| Propiedad | Uso |
|---|---|
Enabled | Activa o desactiva la animacion del offset. |
Speed X | Velocidad horizontal positiva del offset por segundo. |
Speed Y | Velocidad vertical positiva del offset por segundo. |
Scroll Right | Marcado desplaza la textura hacia la derecha; desmarcado la desplaza hacia la izquierda. |
Scroll Down | Marcado desplaza la textura hacia abajo; desmarcado la desplaza hacia arriba. |
API de Texture Scroller
| Funcion | Uso | Ejemplo |
|---|---|---|
TextureScroller.get(object) | Devuelve el componente. | TextureScroller.get(object) |
TextureScroller.setEnabled(object, enabled) | Activa o detiene el scroll. | TextureScroller.setEnabled(object, true) |
TextureScroller.setSpeed(object, x, y) | Cambia la velocidad de los dos ejes. | TextureScroller.setSpeed(object, 0.5, 0) |
TextureScroller.setDirection(object, right, down) | Cambia la direccion de cada eje con booleanos. | TextureScroller.setDirection(object, true, false) |
TextureScroller.setOffset(object, x, y) | Fija inmediatamente el offset de la textura. | TextureScroller.setOffset(object, 0, 0) |
TextureScroller.getOffset(object) | Devuelve { x, y } con el offset actual. | const offset = TextureScroller.getOffset(object) |
export function start(object) {
TextureScroller.setSpeed(object, 0.4, 0);
}
export function update(object) {
if (Input.getKeyDown("Space")) {
const component = TextureScroller.get(object);
TextureScroller.setEnabled(object, !component.enabled);
}
}
Callbacks en scripts
Si tu objeto tiene un script asignado, puedes exportar estas funciones. El motor las llama cuando el collider del objeto entra, permanece o sale de contacto con otro.
| Funcion | Cuando se llama |
|---|---|
onCollisionEnter(object, collision) | Primer frame de contacto con un collider normal. |
onCollisionStay(object, collision) | Cada frame mientras sigue el contacto. |
onCollisionExit(object, collision) | Cuando termina el contacto. |
onTriggerEnter(object, collision) | Primer frame de contacto con un trigger. |
onTriggerStay(object, collision) | Cada frame mientras sigue dentro del trigger. |
onTriggerExit(object, collision) | Cuando sale del trigger. |
export function onCollisionEnter(object, collision) {
debug(object.name + " choca con " + collision.other.name);
}
export function onTriggerEnter(object, collision) {
if (collision.other.tag === "Coin") {
Destroy(collision.other);
}
}
Datos de collision
| Propiedad | Contenido |
|---|---|
collision.other | El otro objeto del contacto. |
collision.self | El objeto que recibe el callback. |
collision.normal | Direccion de separacion desde el punto de vista de self. |
collision.overlap | Profundidad de solapamiento. |
collision.point | Punto aproximado del contacto. |
collision.isTrigger | true si el contacto incluye un trigger. |
API Collision
| Funcion | Uso | Ejemplo |
|---|---|---|
Collision.check(a, b) | Comprueba si dos objetos estan colisionando ahora. | Collision.check(player, enemy) |
Collision.all(object) | Devuelve los contactos actuales de un objeto. | Collision.all(object) |
Collision.contacts() | Devuelve todos los contactos del frame. | Collision.contacts() |
export function update(object, deltaTime) {
const enemy = FindByName("Enemy");
const hit = Collision.check(object, enemy);
if (hit) {
debug("Tocando enemigo");
}
}
Events y Time
Events
Events comunica scripts sin buscar ni referenciar directamente otros objetos. Los
eventos se limpian al cambiar de escena.
Events.on(name, callback) | Escucha un evento y devuelve una funcion para dejar de escucharlo. |
Events.once(name, callback) | Escucha solamente la siguiente emision. |
Events.emit(name, data) | Envia datos a todos los oyentes. |
Events.off(name, callback) | Elimina un callback concreto. |
Events.clear(name) | Limpia un evento; sin nombre limpia todos. |
Events.count(name) | Numero de oyentes. |
export function start(object) {
Events.on("player-hit", data => {
UI.setText("HealthText", `Vida: ${data.health}`);
});
}
export function hitPlayer(health) {
Events.emit("player-hit", { health });
}
Time
Time.deltaTime | Delta escalado del frame. |
Time.unscaledDeltaTime | Delta real, incluso con pausa o camara lenta. |
Time.fixedDeltaTime | Paso fijo del motor. |
Time.time, Time.unscaledTime | Tiempo acumulado escalado y real. |
Time.frameCount | Frames procesados. |
Time.timeScale | Escala global: 1 normal, 0.5 camara lenta, 0 detenido. |
Time.pause(), resume(), isPaused() | Control de pausa. |
export function update(object) {
if (Input.getKeyDown("P")) {
if (Time.isPaused()) Time.resume();
else Time.pause();
}
if (Input.getKeyDown("T")) {
Time.timeScale = 0.35;
}
}
Time.pause() solo detiene el tiempo escalado. Para detener de forma coordinada todo el
juego utiliza la API global Game explicada a continuación.
Pausa global del juego
Game.pause() aplica una pausa completa y segura tanto en Editor Play como en el juego publicado en GameCrom.
Detiene scripts normales, física, colisiones, animaciones, partículas, tweens, pathfinding, cámara y
audio. El juego continúa dibujándose y Input sigue disponible para controlar el menú.
Game.pause() | Pausa el juego. Devuelve true si cambió el estado. |
Game.resume() | Reanuda sin saltos en animaciones ni partículas. |
Game.togglePause() | Alterna pausa y reanudación. |
Game.isPaused() | Indica si la pausa global está activa. |
Cómo pausar y reanudar
export function update(object, deltaTime) {
// update deja de ejecutarse después de pausar.
if (Input.getKeyDown("Escape") || Input.getButtonDown("Start")) {
Game.pause();
UI.show("PauseMenu");
}
}
export function pausedUpdate(object, unscaledDeltaTime) {
// Solo se ejecuta durante la pausa global.
if (Input.getKeyDown("Escape") || Input.getButtonDown("Start")) {
UI.hide("PauseMenu");
Game.resume();
}
}
Para reanudar desde un script usa pausedUpdate(object, unscaledDeltaTime), porque
update, fixedUpdate y lateUpdate permanecen detenidos. No uses
Game.togglePause() solamente dentro de update: después de pausar ese callback
ya no se ejecutará. unscaledDeltaTime permite animar manualmente una interfaz de pausa.
APIs de componentes adicionales
MovingPlatform.get(object) | Obtiene el componente. |
MovingPlatform.setEnabled(object, value) | Activa o desactiva. |
MovingPlatform.setSpeed(object, speed) | Cambia velocidad. |
MovingPlatform.setMovement(object, x, y) | Cambia recorrido. |
MovingPlatform.setPingPong(object, value) | Controla ida y vuelta. |
MovingPlatform.reset(object) | Reinicia su estado. |
Rotation.get(object) | Obtiene Rotation. |
Rotation.setEnabled(object, value) | Activa o desactiva. |
Rotation.setSpeed(object, speed) | Cambia grados por segundo. |
Rotation.reverse(object) | Invierte el sentido de giro actual. Si la velocidad es 0, inicia el giro a -90 grados por segundo. |
Rotation.setPivot(object, x, y) | Cambia pivote. |
Rotation.reset(object) | Reinicia la rotacion acumulada. |
Ladder.get(object), Ladder.setEnabled(object, value) | Consulta o activa una escalera. |
Light.get(object), Light.setEnabled(object, value) | Consulta o activa una luz. |
Light.setColor(object, color) | Cambia color hexadecimal. |
Light.setIntensity(object, value) | Intensidad entre 0 y 1. |
Light.setRadius(object, radius) | Cambia radio. |
Light.setEffect(object, effect, options) | Efecto y opciones speed, amount y color. |
const platform = FindByName("Lift");
MovingPlatform.setSpeed(platform, 120);
MovingPlatform.setMovement(platform, 0, -300);
export function onTriggerEnter(object, collision) {
if (collision.other.tag === "Inverter") {
Rotation.reverse(object);
}
}
const alarm = FindByName("AlarmLight");
Light.setColor(alarm, "#ff2020");
Light.setEffect(alarm, "alarm", { speed: 3, amount: 0.8 });
Guardar partidas con Save
Save guarda objetos completos por slot y proyecto. Para opciones pequeñas sigue siendo
adecuado PlayerPrefs; para partidas usa Save.
No necesitas cambiar el código: en un juego publicado, Save utiliza la nube si el jugador ha iniciado sesión y almacenamiento local si juega como invitado. Cada cuenta y cada juego mantienen sus propios slots.
Save.write(slot, data, metadata) | Guarda datos y metadatos opcionales. |
Save.read(slot, fallback) | Lee los datos. |
Save.info(slot) | Fecha y metadatos sin cargar la partida. |
Save.exists(slot) | Comprueba el slot. |
Save.delete(slot) | Borra un slot. |
Save.list() | Lista slots ordenados por fecha. |
Save.clear() | Borra todas las partidas del proyecto. |
Save.write("slot1", {
scene: Scene.current,
score: Project.vars.score,
lives: 3,
player: { x: object.x, y: object.y }
}, {
title: "Partida principal"
});
const game = Save.read("slot1", null);
if (game) {
Project.vars.score = game.score;
object.x = game.player.x;
object.y = game.player.y;
}
Los datos deben poder convertirse a JSON. No guardes funciones, elementos HTML, Audio ni referencias circulares.
Archivos TXT y JSON
Files sirve exclusivamente para leer recursos .txt y .json incluidos por el desarrollador en assets/data/. Es una API de solo lectura: no crea, modifica ni elimina archivos durante la ejecución.
Datos internos del proyecto — assets/data/
Abre la pestaña Data del panel de Recursos. Desde ella puedes importar archivos
.txt y .json, o crear uno nuevo con New TXT y
New JSON. Los archivos se guardan en assets/data/ y el botón
Open in VS Code los abre directamente en Visual Studio Code. También puedes usar
subcarpetas escribiéndolas en el nombre, por ejemplo dialogues/es.json.
assets/data/ es siempre de solo lectura durante el juego. Sus archivos
forman parte del proyecto y se incluyen en el paquete publicado, pero un script no puede modificarlos ni
eliminarlos. Para cambiar su contenido debes volver al proyecto, editarlo con VS Code y publicar una nueva versión.
// Leer contenido preparado por el desarrollador
const traducciones = await Files.readJSON("assets/data/translations/es.json", {});
const dialogos = await Files.readText("assets/data/dialogos.txt", "");
| Método | Descripción |
|---|---|
await Files.readText(path, fallback?) | Lee un recurso .txt de assets/. |
await Files.readJSON(path, fallback?) | Lee y convierte un recurso .json de assets/. |
Para controlar errores, usa try/catch y consulta error.code: NOT_FOUND, INVALID_JSON o ACCESS_DENIED.
La ruta debe comenzar por assets/. Las rutas user/... y los métodos de escritura, listado, comprobación y borrado no existen. Usa PlayerPrefs para datos pequeños y Save para partidas o datos complejos.
Guardado local y en la nube
Qué sistema debes utilizar
| Sistema | Uso recomendado | Persistencia |
|---|---|---|
PlayerPrefs | Volumen, idioma, controles, calidad gráfica y otras preferencias. | Nube con sesión iniciada; local para invitados y Editor Play. |
Save | Partidas, niveles, inventario, puntuación, campaña y puntos de control. | Nube con sesión iniciada; local para invitados y Editor Play. |
PlayerPrefs y Save guardan inmediatamente en local. Con la sesión iniciada, GameCrom agrupa los cambios y los sincroniza en una sola petición cada dos minutos, al salir del juego o al volver a GameCrom. Si el envío al cerrar falla, conserva la cola local y la reintenta en la siguiente sesión. Files no forma parte del guardado: solo lee recursos empaquetados en assets/.
Dónde se guardan los datos
- Editor Play: en el almacenamiento local del editor.
- Juego publicado, jugador identificado: en el servidor de GameCrom, separado por cuenta y juego.
- Juego publicado, invitado: en el almacenamiento local del navegador.
El guardado en la nube permite recuperar los datos al iniciar sesión desde otro dispositivo. El guardado de invitado pertenece únicamente a ese navegador y puede perderse al borrar sus datos o usar navegación privada.
Uso recomendado
// Preferencias del dispositivo
PlayerPrefs.setNumber("volume", 0.8);
PlayerPrefs.setString("language", "es");
// Progreso de la partida
Save.write("autosave", {
level: 4,
score: 12500,
player: { x: object.x, y: object.y }
});
const data = Save.read("autosave", null);
Guarda en puntos de control y después de cambios importantes. No esperes únicamente al cierre de la pestaña o de la aplicación, porque un cierre forzado puede impedir la última escritura.
Pathfinding
Pathfinding.findPath usa A* sobre una cuadricula temporal. Los objetos con collider
activo bloquean celdas; los triggers no bloquean. No requiere Tilemap.
Pathfinding.findPath(start, end, options) | Devuelve puntos de mundo o un array vacio. |
Pathfinding.follow(object, path, speed, options) | Hace que el objeto siga la ruta. |
Pathfinding.stop(object) | Detiene el seguimiento. |
Pathfinding.isFollowing(object) | Comprueba si sigue una ruta. |
Opciones principales: cellSize, diagonal, padding,
marginCells, maxNodes e ignore. Un cellSize pequeño encuentra
rutas mas precisas pero cuesta mas CPU.
export function start(object) {
const player = FindByTag("Player");
const path = Pathfinding.findPath(object, player, {
cellSize: 32,
diagonal: true,
padding: 6,
ignore: [object, player]
});
Pathfinding.follow(object, path, 110, {
arriveDistance: 3,
onComplete(enemy) {
debug(enemy.name + " ha llegado");
}
});
}
export function update(object) {
if (Input.getKeyDown("Escape")) {
Pathfinding.stop(object);
}
}
Shapes: Square, Circle y Line
Las formas son GameObjects nativos. Se crean desde Add GameObject, se editan en el Inspector y conservan jerarquia, Z, color, opacidad, scripts, prefabs y colisiones.
Shape.create(type, options) | Crea Square, Circle o Line durante Play. |
Shape.createLine(x1, y1, x2, y2, options) | Crea una linea entre dos puntos. |
Shape.setLine(object, x1, y1, x2, y2, options) | Mueve y redimensiona una linea existente. |
Shape.setStart(object, x, y) / Shape.setEnd(object, x, y) | Mueve solamente el punto inicial o final. |
Shape.getPoints(object) | Devuelve { start, end } con las dos posiciones. |
Shape.setColor / setOpacity / setVisible / setSize | Modifica las propiedades visuales comunes. |
let mark;
export function start() {
mark = Shape.createLine(100, 120, 340, 260, {
width: 24,
cap: "round",
color: "#ef9cbd",
opacity: 0.35,
z: 4
});
}
export function update() {
if (Input.getMouseButton(0)) {
Shape.setEnd(mark, Input.mouseWorldX, Input.mouseWorldY);
}
}
En el editor, selecciona Line y arrastra sus dos manejadores para cambiar Start Position o End Position. La longitud y rotacion se adaptan automaticamente. Los extremos disponibles son round, butt y square.
Pixel Canvas
El objeto Pixel Canvas es una imagen dinamica y escalable cuyo contenido procede de un framebuffer controlado por scripts. Sirve para emuladores, programas de dibujo, minimapas, pantallas, efectos procedurales y juegos basados directamente en pixeles.
Crea Add GameObject > Pixel Canvas y configura su resolucion interna. El tamano y la escala del objeto controlan el tamano visible; su resolucion controla cuantos pixeles contiene el framebuffer.
PixelCanvas.create(object, width, height, options) | Crea o reemplaza la superficie. |
PixelCanvas.get(object) | Devuelve la superficie existente. |
PixelCanvas.getOrCreate(object) | Obtiene o crea usando la configuracion del objeto. |
surface.getBuffer() | Buffer RGBA Uint8ClampedArray; cuatro bytes por pixel. |
surface.getIndexBuffer() | Buffer Uint8Array de indices para paletas de hasta 256 colores. |
surface.setPixel(x, y, color) | Dibuja un pixel. |
surface.clear(color) | Limpia toda la superficie. |
surface.fillRect(x, y, w, h, color) | Rellena un rectangulo. |
surface.drawLine(x0, y0, x1, y1, color) | Dibuja una linea. |
surface.setPalette(colors) | Define la paleta del modo indexado. |
surface.present() | Publica los cambios del buffer para renderizarlos. |
let screen;
export function start(object) {
screen = PixelCanvas.create(object, 256, 192, {
indexed: true
});
screen.setPalette([
"#000000", "#0000d7", "#d70000", "#d700d7",
"#00d700", "#00d7d7", "#d7d700", "#d7d7d7"
]);
screen.clear(0).present();
}
export function update(object) {
const pixels = screen.getIndexBuffer();
pixels[40 * screen.width + 80] = 6;
screen.markDirty();
screen.present();
}
Para maximo rendimiento modifica directamente el buffer y llama a markDirty() antes de
present(). Con Auto Present activo, el renderer publica automaticamente
cualquier superficie marcada como modificada.
Engine, tipos y contrato de API
Engine.version | Version del motor. |
Engine.apiVersion | Version del contrato de scripts. |
Engine.isEditor | true en Editor Play y false en el juego publicado en GameCrom. |
Engine.platform | Plataforma comunicada por el sistema. |
export function start(object) {
debug({
engine: Engine.version,
api: Engine.apiVersion,
editor: Engine.isEditor,
platform: Engine.platform
});
}
IntelliSense en VS Code
GameCrom prepara cada proyecto automaticamente para VS Code. Al crear o abrir un script genera
.gamecrom/gamecrom-api.d.ts y, si el proyecto no tiene uno propio, un
jsconfig.json. Al pulsar Edit, VS Code abre la raiz completa del proyecto
y ofrece sugerencias para las APIs globales y para metodos del objeto como translate,
addForce, setVelocity y setGravity. No es necesario instalar una extension.
GameCrom no reemplaza un jsconfig.json creado por el desarrollador.
Tambien incluye snippets para las funciones principales. Escribe, por ejemplo,
export function update y pulsa Tab para completar la funcion. Estan disponibles
start, update, onCollisionEnter, onCollisionExit,
onTriggerEnter y onTriggerExit. Las anotaciones generadas activan el
autocompletado contextual dentro de cada callback. Los snippets normales usan solo los parametros
necesarios. Para recibir propiedades publicas usa export function start properties o
export function update properties.
El archivo maestro de tipos es DOCUMENTOS/gamecrom-2d-studio-api.d.ts. La prueba
node TESTS/runtimeApiContract.mjs valida matematicas, eventos, tiempo, Random, Save,
Pathfinding y PixelCanvas.
API Payments: micropagos con Acroms
Payments permite vender desbloqueos permanentes y consumibles dentro de un juego publicado en GameCrom. Todas las compras usan Acroms y se procesan inmediatamente en el servidor. El servidor obtiene y valida la cuenta, el Game ID, el producto, el tipo, el precio y el saldo; después descuenta los Acroms, concede el producto y registra los movimientos en una única transacción atómica e idempotente. La promesa de compra solo se resuelve cuando el servidor ha confirmado toda la operación.
Las compras, propiedades permanentes y cantidades consumibles están completamente separadas del guardado normal. Nunca uses PlayerPrefs, Save ni Files para conceder, almacenar o verificar contenido comprado con Acroms. Consulta siempre Payments.state(); el juego no puede modificar el saldo, el precio, la propiedad ni el inventario del servidor.
Crear productos desde la ficha del juego
- Entra en Developer, abre la ficha del juego y baja a Micropagos dentro del juego.
- Pulsa Nuevo producto. El panel se abre limpio; Cancelar lo cierra sin guardar.
- Escribe el título, una clave como
diamonds_100y la descripción de lo que recibe el jugador. La clave identifica el producto en tus scripts y no puede cambiar después de crearlo. - Indica el precio en Acroms, siempre entero y mayor que cero. 100 Acroms equivalen siempre a 1 €.
- Elige Desbloqueo permanente para una compra única, o Consumible para compras repetibles. En un consumible indica las unidades entregadas por compra; por ejemplo, 100 diamantes. El tipo tampoco cambia después de crear el producto.
- Marca Disponible para comprar y pulsa Crear producto. Desde Editar puedes cambiar el título, la descripción, el precio, las unidades del consumible y su disponibilidad. Desactivarlo retira el producto de la tienda sin borrar las compras existentes.
El precio del juego completo y sus micropagos son independientes: un juego gratuito también puede ofrecer micropagos. En administración se muestran todos los productos de la ficha, incluidos los inactivos.
Utilizarlos en scripts del editor
Configura el catálogo en la web y programa su interfaz desde el editor con Payments. Usa exactamente la clave configurada. No envíes precios ni usuarios desde el script: GameCrom los obtiene del servidor.
export async function consultarProductos() {
if (!Payments.isAvailable()) return;
const catalog = await Payments.catalog();
const state = await Payments.state();
debug(catalog.products);
debug(Payments.quantity("diamonds_100", state));
}
export async function comprarDiamantes() {
if (!Payments.isAvailable()) {
debug("Los micropagos reales se prueban en GameCrom.");
return;
}
try {
const result = await Payments.purchase("diamonds_100");
debug(`Unidades disponibles: ${result.quantity}`);
} catch (error) {
debug(error.message); // Cancelación, falta de saldo o error.
}
}
export async function gastarDiamantes() {
if (!Payments.isAvailable()) return;
try {
const result = await Payments.consume("diamonds_100", 5);
debug(`Quedan ${result.quantity} unidades`);
} catch (error) {
debug(error.message);
}
}
Llama a estas funciones desde los eventos de tus botones siguiendo la API UI documentada. purchase() abre una confirmación en la página de GameCrom; no concedas el producto antes de que su promesa termine correctamente. consume() descuenta unidades del inventario del servidor, no Acroms.
Pruebas y publicación
En Play del editor, Payments.isAvailable() devuelve false y no hay cargos reales. Puedes simular la interfaz con variables temporales del proyecto, pero esa simulación no representa una compra. Para probar el flujo real, publica la versión actual desde Studio, abre el juego en GameCrom e inicia sesión con una cuenta con saldo de Acroms. Prueba tanto confirmar como cancelar, los desbloqueos permanentes y el consumo de unidades.
Consulta siempre Payments.state() al cargar el juego para recuperar la propiedad y el inventario. Nunca uses Save ni PlayerPrefs para conceder o demostrar compras. Puedes pasar una clave de idempotencia opcional a purchase() y consume() para reintentar la misma operación sin repetir el cargo o consumo; conserva esa misma clave para el reintento y usa otra para una operación nueva.
Tipos de producto
| Tipo | Uso |
|---|---|
one_time | Compra única permanente: desbloquear el juego completo, niveles o quitar publicidad. |
consumable | Compra repetible: diamantes, monedas, vidas u otras unidades consumibles. |
Métodos
Payments.isAvailable() | Indica si el juego se está ejecutando dentro de GameCrom con micropagos disponibles. |
await Payments.catalog() | Obtiene los productos configurados para el juego. |
await Payments.state() | Obtiene saldo de Acroms, desbloqueos y cantidades consumibles. |
await Payments.purchase(productKey) | Compra el producto. Los productos one_time solo pueden adquirirse una vez. |
await Payments.consume(productKey, cantidad) | Descuenta unidades de un producto consumable en el servidor. |
Payments.owns(productKey, state) | Comprueba un desbloqueo permanente en un estado ya obtenido. |
Payments.quantity(productKey, state) | Lee la cantidad disponible de un consumible. |
Desbloquear el resto del juego
export async function comprobarDesbloqueo() {
const state = await Payments.state();
return Payments.owns("full_game", state);
}
export async function comprarJuegoCompleto() {
const result = await Payments.purchase("full_game");
if (result.owned) Scene.load("Nivel2");
}
Comprar y gastar diamantes
export async function comprarDiamantes() {
const result = await Payments.purchase("diamonds_100");
debug(`Diamantes disponibles: ${result.quantity}`);
}
export async function gastarDiamantes() {
const result = await Payments.consume("diamonds_100", 5);
debug(`Quedan ${result.quantity} diamantes`);
}
Durante Play en el editor no se realizan compras. Usa Payments.isAvailable() si necesitas mostrar una interfaz alternativa. No uses Save ni PlayerPrefs como prueba de una compra: la propiedad y los consumibles siempre proceden del servidor.
Probar la interfaz en Editor Play
export async function comprobarAcceso() {
if (Payments.isAvailable()) {
// Juego publicado: consulta siempre el estado real del servidor.
const state = await Payments.state();
Project.vars.fullGame = Payments.owns("full_game", state);
Project.vars.diamonds = Payments.quantity("diamonds_100", state);
return;
}
// Editor Play: simulación local exclusiva para probar la interfaz.
Project.vars.fullGame = true;
Project.vars.diamonds = 100;
}
Esta simulación no compra nada, no descuenta Acroms y no prueba saldo, atomicidad, idempotencia, historial ni concesiones del servidor. Para validar el flujo económico real debes publicar el juego en GameCrom y probarlo con un usuario identificado. No guardes esta simulación con PlayerPrefs o Save como si fuese una compra.
API Application: salir del juego
Usa Application.quit() para abandonar el juego desde cualquier script. La misma llamada
funciona durante Play en el editor y en un juego publicado en GameCrom. Application.exit() es un alias equivalente.
| Entorno | Resultado |
|---|---|
| Play del editor | Detiene Play y vuelve a la escena sin cerrar el editor. |
| Juego web en GameCrom | Cierra el reproductor web y finaliza la sesion de partida. |
Salir directamente
export async function salirDelJuego() {
await Application.quit();
}
Puedes llamar a esta funcion desde la logica de un boton de menu, una pantalla de Game Over o
cualquier otro script. La promesa devuelve true si la solicitud se ha enviado y
false si otro codigo ha cancelado la salida.
Salir al pulsar Escape
export function start(object) {
// No hace falta preparar nada al iniciar.
}
export async function update(object, deltaTime) {
if (Input.getKeyDown("Escape")) {
await Application.quit("escape-key");
}
}
Guardar antes de salir
export async function salirGuardando(object) {
PlayerPrefs.setInt("record", Project.vars.record || 0);
PlayerPrefs.setJSON("configuracion", Project.vars.configuracion || {});
PlayerPrefs.save();
await Application.quit("main-menu");
}
Guarda primero y solicita la salida despues. No pongas operaciones largas despues de
Application.quit(), porque el juego puede cerrarse inmediatamente.
Cancelar temporalmente la salida
let hayCambiosSinGuardar = true;
export async function intentarSalir() {
if (hayCambiosSinGuardar) {
window.addEventListener("gamecrom:before-quit", event => {
event.preventDefault();
debug("Guarda la partida antes de salir");
}, { once: true });
}
const saliendo = await Application.quit("main-menu");
debug({ saliendo }); // false si se ha cancelado
}
export async function guardarYSalir() {
PlayerPrefs.setInt("nivel", Project.vars.nivel || 1);
hayCambiosSinGuardar = false;
await Application.quit("saved-game");
}
Antes de cerrar se emite el evento cancelable gamecrom:before-quit. Su propiedad
event.detail.reason contiene el motivo enviado a quit. El listener debe
decidir de forma sincrona si cancela la salida mediante event.preventDefault().
Metodos disponibles
| Metodo | Uso |
|---|---|
await Application.quit(reason?) | Solicita una salida limpia y devuelve true o false. |
await Application.exit(reason?) | Alias de Application.quit(). |
En la ficha del juego del Developer Dashboard declara ordenador (teclado/ratón), móvil/tablet (táctil) y gamepad. La ficha muestra también los dispositivos aprobados por el admin. Cambiar tu declaración no cambia automáticamente la aprobación ni el catálogo; la decisión final corresponde a GameCrom.
GameCrom valida los dispositivos compatibles durante la revisión: escritorio (teclado/ratón), móvil/tablet (táctil) y, adicionalmente, gamepad. La declaración de controles del creador no sustituye esa aprobación. El catálogo y la portada muestran por defecto los juegos aprobados para el dispositivo actual; el catálogo permite cambiar el filtro. Biblioteca y favoritos conservan tus juegos y avisan de incompatibilidades. Cada nueva versión requiere revisión.
Los juegos publicados se ejecutan en games.gamecrom.com, aislados de la sesión de la web. Usa las APIs documentadas: PlayerPrefs y Save mantienen su interfaz y el guardado local con sincronización automática. No accedas a cookies de la plataforma ni a sus páginas administrativas desde un juego.
20. Publicar en GameCrom
Crea primero la ficha del juego en tu Developer Dashboard de la web y copia su Game ID. En Project Settings, inicia sesión, pega ese ID y pulsa Publish on GameCrom. El editor guarda el proyecto, genera un paquete temporal y lo envía de forma privada.
El apartado Tamaño del juego analiza el proyecto antes de publicarlo. Muestra el peso total, subtotales por imágenes, audio, vídeo, scripts, escenas, prefabs, fuentes, datos y otros archivos, además del tamaño individual de cada archivo. El límite de publicación es 300 MB. A partir de 100 MB, Studio recuerda que los juegos más pequeños cargan más rápido.
El juego queda en revisión. No aparecerá en el catálogo hasta que un administrador de GameCrom lo apruebe. Si envías otra versión, también debe revisarse. GameCrom Studio es gratuito. La cuenta de GameCrom se utiliza para publicar y para acceder a los servicios online de la plataforma.
Los juegos publicados se ejecutan exclusivamente mediante el reproductor de GameCrom y una sesión temporal. Su acceso puede ser gratuito o requerir una compra con Acroms según la ficha configurada por el creador. No incluyas secretos, claves privadas ni lógica sensible en el juego.
21. Consejos de uso
- Usa
deltaTimepara que el movimiento no dependa de los FPS. - Comprueba siempre si
FindByNameoFindByTagdevuelvennull. - Usa tags para categorias como
Enemy,Player,PickupoTarget. - Si un script se asigna a varios objetos, cada objeto recibira su propia llamada a
startyupdate. - Los cambios hechos durante Play son temporales y se restauran al salir de Play.