Esta página aún no está traducida: se muestra la versión en inglés.
Entity presets
Un preset es un paquete con nombre de aspectos de entidad —datos, estados, RPC, eventos, hooks— armado para un caso concreto del juego. Puedes aplicar un preset tal cual, ajustar sus números o derivar el tuyo. Aplicarlo agrega aspectos a tu tipo; no coloca tu tipo por debajo de nada: un preset no es un módulo y no tiene nada propio de lo que heredar. Las estadísticas, las habilidades (ability), los proyectiles, las tablas de botín (drop table) y los objetos del mundo son cinco presets, no cinco subsistemas: la misma declaración, la misma sincronización, el mismo orden de hooks.
Cuándo usarlo
- Algo en tu juego tiene números que se mantienen dentro de sus límites, se regeneran y disparan una transición al llegar a ellos.
- Una acción necesita costo, tiempo de recarga (cooldown), fases y efectos, y debe poder lanzarse con un solo verbo del cliente.
- Algo sale volando, y su impacto debe evaluarse de forma justa para un tirador con lag.
- El botín debe salir de probabilidades ponderadas que se reproduzcan exactamente cuando un jugador reclama por un drop.
- El mapa tiene mobiliario —puertas, botones, trampas, objetos destructibles— con estados que deben sobrevivir a que alguien se una a mitad de la ronda.
- No uses presets cuando una entidad es solo datos sincronizados. Declara los campos y listo.
Quién hace qué
| Actor | Qué hace en esta página |
|---|---|
schema-author | declara estadísticas, habilidades, proyectiles, tablas de botín y objetos del mundo |
room-owner | ajusta los números de los presets, tira las tablas de botín y crea objetos del mundo |
player | lanza habilidades, dispara, recoge botín e interactúa con objetos |
En resumen
Crate de dos presets incluidos y luego crea cada caja con una línea, ajustada a 250 HP// derived once, in the schema
[Entity("crate", Persistence = Persistence.Runtime, Presets = new[] { Preset.WorldObjects, Preset.Stats })]
public class Crate { [Stat(Max = 100, AtMin = "broken")] public Stat Hp; }
// then one line per crate, on the room host
var crate = await room.Create<Crate>(at: pos, tune: c => c.Hp.Max = 250);// derived once, in the schema
@Entity('crate', { persistence: Persistence.Runtime, presets: [Preset.WorldObjects, Preset.Stats] })
export class Crate { @Stat({ max: 100, atMin: 'broken' }) hp: Stat; }
// then one line per crate, on the room host
const crate = await room.create<Crate>({ at: pos, tune: (c) => { c.hp.max = 250; } });# derived once, in the schema
@entity("crate", persistence=Persistence.RUNTIME, presets=[Preset.WORLD_OBJECTS, Preset.STATS])
class Crate:
hp = stat(max=100, at_min="broken")
# then one line per crate, on the room host
crate = await room.create(Crate, at=pos, tune={"hp.max": 250})Todavía no está decidido cómo declarar con atributos en Go (O-1). Los ejemplos llegarán cuando se elija la forma de escribirlo.
// declarations compile into the same pushed model — playserv push from the UE project or CI
UCLASS(PSEntity = (Name = "crate", Persistence = "Runtime", Presets = "world-objects, stats"))
class UCrate : public UObject
{
GENERATED_BODY()
UPROPERTY(PSStat = (Max = 100, AtMin = "broken")) FPSStat Hp;
};
// then one line per crate, on the room host (dedicated server / master-client)
Room->Entities->Of<UCrate>()->Create(FPSIdempotencyKey(CrateId),
[SpawnPosition](UCrate& Crate) { Crate.Position = SpawnPosition; }); // Position — from the world-objects preset
// co_await support ships later: a built-in SDK coroutine wrapper that respects Unreal's GC and threading.// derived once, in the schema
[Entity("crate", Persistence = Persistence.Runtime, Presets = new[] { Preset.WorldObjects, Preset.Stats })]
public class Crate { [Stat(Max = 100, AtMin = "broken")] public Stat Hp; }
// then one line per crate, on the room host
var crate = await room.Create<Crate>(at: pos, tune: c => c.Hp.Max = 250);El modelo
Un preset no introduce conceptos nuevos. Todo lo que agrega se puede expresar con lo que ya ofrece la entidad: aspectos, máquinas de estados, hooks, persistencia.
Qué aporta cada preset y dónde se ajusta.
| Preset | Qué le da el contrato | Dónde se ajusta |
|---|---|---|
stats | un aspecto de características numéricas con límites, regeneración y modificadores, más un hook al alcanzar un umbral: 0 HP se convierte en una transición de la máquina de estados, no en un if en tu código | la declaración del campo; los números se pueden seguir editando en vivo en el panel |
abilities | un aspecto con un conjunto de habilidades, una máquina con las fases de aplicación, y costo y tiempo de recarga | la declaración de la habilidad |
projectiles | un tipo con persistencia runtime, un aspecto de balística y un evento de impacto | la declaración del proyectil: cambiar un solo atributo cambia el modelo de vuelo |
drops | un aspecto de tabla de botín con pesos y un hook después de la muerte | las entradas de la tabla y sus pesos |
world objects | una máquina de estados de un objeto interactivo y un aspecto con la condición de interacción | la declaración del preset, o por instancia al crearla |
| inventory | un tipo con dueño con una ref a un artículo del catálogo, un aspecto de pila con incremento y un tope por dueño con desbordamiento declarado | la declaración del tipo |
Inventory también tiene su propia página.
Qué se cumple en todo preset.
| Siempre | Qué es |
|---|---|
dónde vive | en una entidad, como aspectos: sus datos se sincronizan como cualquier otro dato, sus estados son estados de la entidad, sus RPC son RPC de la entidad y sus hooks se ejecutan en el orden de hooks de la entidad |
el ajuste | es configuración en vivo y no requiere un nuevo deploy; por eso el panel muestra en un mismo árbol el límite de una estadística, un tiempo de recarga y el peso de un drop |
derivar el tuyo | es composición, no herencia: Crate es world-objects más stats, y lo derivado sigue siendo aspectos sobre una entidad |
Errores
- Declarar una estadística, una habilidad, un proyectil, una tabla de botín o un objeto del mundo es un acto de esquema:
fnoadm. Una clave de jugador o de cliente que lo intente recibeforbidden, y no queda nada declarado ni declarado a medias. Es un rechazo distinto de los que un jugador encuentra dentro de una llamada que sí tenía permitido hacer —en tiempo de recarga, sin con qué pagar, sin elitem:key.bronze—, y cada uno de ellos trae su propio código.
El resto de los rechazos de un preset son los de entidad. Dos son propios de los presets:
- Un preset rellenado a medias es un fallo de validación al desplegar. Un preset trae un conjunto coherente: media declaración se rechaza antes de publicarse, en lugar de comportarse de forma extraña en una partida.
- A un preset no se le puede marcar con una propiedad que contradice su propia mecánica: un aspecto para el que el cliente no tiene reglas no se puede declarar predecible, y eso también se detecta al desplegar.
Límites
Los topes son los de entidad: aspectos por tipo, máquinas por tipo, el tamaño de la instancia almacenada, la frecuencia de cambios en una instancia. El único que declara el propio preset es el tope por dueño de un preset con dueño, con uno de tres comportamientos en el límite y sin valor predeterminado: refuse · redirect hacia un contenedor de dueño declarado · discard with event. Las cifras llegarán con el capítulo sobre los límites de la plataforma.