Esta página ainda não foi traduzida: mostrando a versão em inglês.
Entity presets
Um preset é um pacote nomeado de aspectos de entidade — dados, estados, RPC, eventos, hooks — montado para uma situação concreta do jogo. Você aplica um preset, ajusta os números dele ou deriva o seu. Aplicar um preset adiciona aspectos ao seu tipo, mas não coloca o seu tipo embaixo de nada: um preset não é um módulo e não tem nada próprio de que herdar. Stats, habilidades (ability), projéteis, tabelas de drops e objetos do mundo são cinco presets, e não cinco subsistemas: a mesma declaração, a mesma sincronização, a mesma ordem de hooks.
Quando usar
- Algo no seu jogo tem números que ficam dentro de limites, se regeneram e disparam uma transição quando chegam a esses limites.
- Uma ação precisa de custo, cooldown, fases e efeitos, acionados por um único verbo do cliente.
- Algo está em voo, e o acerto precisa ser julgado com justiça para quem atira com lag.
- O loot precisa vir de probabilidades com pesos que se reproduzem exatamente quando um jogador contesta um drop.
- O mapa tem elementos de cenário — portas, botões, armadilhas, objetos destrutíveis — com estados que precisam sobreviver à entrada de alguém no meio da rodada.
- Dispensável quando a entidade é só um conjunto de dados sincronizados. Declare os campos e pronto.
Quem faz o quê
| Ator | O que faz nesta página |
|---|---|
schema-author | declara stats, habilidades, projéteis, tabelas de drops e objetos do mundo |
room-owner | ajusta os números dos presets, sorteia nas tabelas de drops, cria objetos do mundo |
player | usa habilidades, atira, pega loot, interage com objetos |
Resumo
Crate de dois presets prontos e depois crie cada caixa com uma linha, ajustada para 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})Ainda não está decidido como declarar com atributos em Go (O-1). Os exemplos chegam quando a forma de escrita for escolhida.
// 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);O modelo
Um preset não introduz nenhum conceito novo. Tudo o que ele adiciona pode ser expresso com os recursos que a entidade já oferece — aspectos, máquinas de estados, hooks, persistência.
O que cada preset oferece e onde ele é ajustado.
| Preset | O que o contrato oferece | Onde é ajustado |
|---|---|---|
stats | um aspecto de características numéricas com limites, regeneração e modificadores, mais um hook ao atingir um limiar — 0 HP vira uma transição da máquina de estados, e não um if no seu código | a declaração do campo. Os números continuam editáveis ao vivo no painel |
abilities | um aspecto com um conjunto de habilidades, uma máquina de estados das fases de uso, além de custo e cooldown | a declaração da habilidade |
projectiles | um tipo com persistência runtime, um aspecto de balística e um evento de acerto | a declaração do projétil — trocar um único atributo muda o modelo de voo |
drops | um aspecto de tabela de drops com pesos e um hook depois da morte | as entradas e os pesos da tabela |
world objects | uma máquina de estados de objeto interativo e um aspecto com a condição de interação | a declaração do preset, ou cada instância na criação |
| inventory | um tipo com dono, com uma ref para um item do catálogo, um aspecto de pilha com incremento e um teto por dono com comportamento declarado para o excedente | a declaração do tipo |
Inventory também tem uma página própria.
O que vale para todo preset.
| Sempre | O que é |
|---|---|
onde ele fica | em uma entidade, como aspectos: os dados dele sincronizam como quaisquer outros, os estados são estados da entidade, os RPCs são RPCs da entidade e os hooks rodam na ordem de hooks da entidade |
ajuste | é configuração ao vivo, e não um novo deploy. Por isso o painel mostra o limite de um stat, um cooldown e o peso de um drop na mesma árvore |
derivar o seu | é composição, e não criação de subclasse: Crate é world-objects mais stats, e o resultado continua sendo um conjunto de aspectos em uma entidade |
Erros
- Declarar um stat, uma habilidade, um projétil, uma tabela de drops ou um objeto do mundo é uma operação de esquema —
fnouadm. Uma chave de jogador ou de cliente que tente fazer isso recebeforbidden, e nada fica declarado, nem pela metade. Essa recusa é diferente das que um jogador encontra dentro de uma chamada que ele tinha permissão para fazer — cooldown ativo, saldo insuficiente, falta doitem:key.bronze—, e cada uma delas traz o próprio código.
As demais recusas de um preset são as da entidade. Duas são específicas dos presets:
- Um preset preenchido pela metade é uma falha de validação no deploy. Um preset traz um conjunto coerente: uma declaração pela metade é recusada antes de ir para produção, em vez de se comportar de um jeito estranho no meio de uma partida.
- Um preset não pode ser marcado com uma propriedade que a própria mecânica dele contradiz — um aspecto para o qual o cliente não tem regras não pode ser declarado com predição, e isso também é detectado no deploy.
Limites
Os tetos são os da entidade — aspectos por tipo, máquinas de estados por tipo, o tamanho da instância armazenada, a taxa de mudanças em uma instância. O único que o próprio preset declara é o teto por dono de um preset com dono, com um de três comportamentos na fronteira e sem padrão: refuse · redirect para um compartimento declarado do dono · discard with event. Os números chegam com o capítulo sobre os limites da plataforma.