Esta página ainda não foi traduzida: mostrando a versão em inglês.
Map
O mundo estático: limites, terreno, obstáculos e “para onde as coisas podem ir?”. O modelo físico é, de propósito, muito mais simples que o visual: primitivas com uma base e uma altura, camadas com regras e uma única consulta de posição válida que todos os outros módulos reutilizam.
Quando usar
- Você precisa de um mundo estático (limites, terreno, obstáculos) que o servidor possa consultar, e não só renderizar.
- Spawns, drops e decorações precisam cair em lugares válidos: uma única consulta
RandomPosition, baseada em regras, sem atalhos. - As arenas devem ser geradas de novo a cada partida: um
Seeddeclarado reproduz o mesmo mapa num relatório de bug. - Caixas e paredes quebram e voltam: objetos destrutíveis com HP e timers de respawn.
- Bots e projéteis precisam de respostas de raycast e de linha de visão contra o conjunto de obstáculos.
- Dispensável quando o mundo é puramente visual e nenhum código de servidor pergunta para onde as coisas podem ir.
Quem faz o quê
| Ator | O que faz nesta página |
|---|---|
schema-author | declara mapas, primitivas de obstáculo, objetos destrutíveis, camadas e suas regras |
room-owner | vincula um mapa a uma sala (room); pede posições de spawn; faz raycasts |
operator | coloca ou remove obstáculos e camadas pelo painel |
Resumo
arena declarado: seed e limites, terreno, rochas, caixas com respawn, uma camada de regras[Map("arena", Seed = 42, Bounds = "160x160")]
public static class Arena
{
[Terrain(HeightNoise = 0.3f)] public static Terrain Height; // 3D height field
[Scatter("rock", Count = 40, MinSpacing = 6)] public static ObstacleSet Rocks;
[Destructible("crate", Count = 12, Hp = 100, RespawnAfter = "30s")] public static ObstacleSet Crates;
[Layer("ground", NotInside = "water")] public static Layer Ground;
}
// or: Maps.Named("arena-caves-v3") — authored in the panel or loaded from an asset@Map('arena', { seed: 42, bounds: '160x160' })
export class Arena {
@Terrain({ heightNoise: 0.3 }) height: Terrain; // 3D height field
@Scatter('rock', { count: 40, minSpacing: 6 }) rocks: ObstacleSet;
@Destructible('crate', { count: 12, hp: 100, respawnAfter: '30s' }) crates: ObstacleSet;
@Layer('ground', { notInside: 'water' }) ground: Layer;
}
// or: Maps.named('arena-caves-v3') — authored in the panel or loaded from an asset@Map("arena", seed=42, bounds="160x160")
class Arena:
height = terrain(height_noise=0.3) # 3D height field
rocks = scatter("rock", count=40, min_spacing=6)
crates = destructible("crate", count=12, hp=100, respawn_after="30s")
ground = layer("ground", not_inside="water")
# or: maps.named("arena-caves-v3") — authored in the panel or loaded from an assetAinda não está decidido como declarar com atributos em Go (O-1). Os exemplos chegam quando a forma de escrita for escolhida.
USTRUCT(PSMap = (Name = "arena", Seed = 42, Bounds = "160x160"))
struct FArena
{
GENERATED_BODY()
UPROPERTY(PSTerrain = (HeightNoise = "0.3")) FPSTerrain Height; // 3D height field
UPROPERTY(PSScatter = (Obstacle = "rock", Count = 40, MinSpacing = 6)) FPSObstacleSet Rocks;
UPROPERTY(PSDestructible = (Obstacle = "crate", Count = 12, Hp = 100,
RespawnAfter = "30s")) FPSObstacleSet Crates;
UPROPERTY(PSStratum = (Name = "ground", NotInside = "water")) FPSStratum Ground;
};
// or: PS::Maps::Named(TEXT("arena-caves-v3")) — authored in the panel or loaded from an asset
// declarations compile into the same pushed model — playserv push from the UE project or CI[Map("arena", Seed = 42, Bounds = "160x160")]
public static class Arena
{
[Terrain(HeightNoise = 0.3f)] public static Terrain Height; // 3D height field
[Scatter("rock", Count = 40, MinSpacing = 6)] public static ObstacleSet Rocks;
[Destructible("crate", Count = 12, Hp = 100, RespawnAfter = "30s")] public static ObstacleSet Crates;
[Layer("ground", NotInside = "water")] public static Layer Ground;
}
// or: Maps.Named("arena-caves-v3") — authored in the panel or loaded from an assetScatter e Destructible são geradores de posicionamento, e não sorteios em runtime. O gerador é resolvido quando a versão do mapa é publicada: as quarenta rochas viram quarenta primitivas declaradas, e a versão publicada carrega as primitivas, não a regra. Por isso, o mesmo Seed gera as mesmas quarenta rochas na partida, no replay e no relatório de bug — e os limites de geometria são verificados uma única vez, nesse conjunto resolvido, antes que a versão chegue a um ambiente.
A consulta que todo o resto faz:
RandomPosition: um spawn justo, no chão, longe dos jogadores, sem repetirvar spawn = map.RandomPosition(r =>
{
r.Layer("ground");
r.AwayFrom(players, minDistance: 12);
r.NoRepeat(lastN: 3);
});const spawn = map.randomPosition((r) => {
r.layer('ground');
r.awayFrom(players, { minDistance: 12 });
r.noRepeat({ lastN: 3 });
});spawn = map.random_position(rules=lambda r: (
r.layer("ground"),
r.away_from(players, min_distance=12),
r.no_repeat(last_n=3),
))Ainda não está decidido como declarar com atributos em Go (O-1). Os exemplos chegam quando a forma de escrita for escolhida.
// Dedicated-server host: place a spawn through the same rule-based query
Map->Positions->GetRandom({ .Stratum = PSKeys::Strata::Ground,
.AwayFrom = Players,
.MinDistance = 12.f,
.NoRepeatLastN = 3 },
TPSOnResult<FVector>::CreateLambda([](const TPSResult<FVector>& Result)
{
if (!Result.HasValue()) { return; }
PlaceSpawn(Result.Value());
}));
// co_await support ships later: a built-in SDK coroutine wrapper that respects Unreal's GC and threading.var spawn = map.RandomPosition(r =>
{
r.Layer("ground");
r.AwayFrom(players, minDistance: 12);
r.NoRepeat(lastN: 3);
});O modelo
Duas camadas, declaradas por pessoas diferentes.
| Camada | O que contém e quem declara |
|---|---|
estática | terreno com altura, primitivas de obstáculo, limites e locais — conteúdo criado pela equipe |
dinâmica | obstáculos trazidos por entidades em runtime: portas, objetos destrutíveis, plataformas. Por isso, um objeto destrutível é uma entidade com ciclo de vida, estados e dono, e só vira mapa na parte em que traz um obstáculo: uma rocha estática é declarada no mapa, enquanto uma porta é uma entidade que traz um obstáculo. Esses obstáculos não têm ciclo de vida próprio aqui: o ciclo de vida é da entidade |
O que um mapa declara.
| Declara | O que é |
|---|---|
key e version | um mapa é conteúdo criado pela equipe: declarado em código, endereçado por key e versionado — a versão faz parte do que uma sala referencia. Alterar a geometria de uma versão lançada é proibido; uma edição é uma nova versão |
terreno | um campo de alturas — uma grade regular com um passo declarado, e esse passo é um limite de precisão declarado; por isso, uma consulta de altura responde de acordo com ele, e não com exatidão. O terreno pode não existir: uma arena no vazio é válida |
obstáculos | um conjunto fechado de primitivas — caixa, esfera, cápsula, envoltória convexa (convex hull) com um limite declarado de vértices. Uma malha de triângulos arbitrária não é aceita, e é isso que torna possível verificar no servidor |
tipo de passabilidade por obstáculo | intransponível · transponível para uma classe declarada · bloqueia apenas a linha de visão. A mesma primitiva serve como parede e como arbusto, e a diferença é declarada, e não modelada duas vezes |
limites | o volume fora do qual uma posição é inadmissível |
estratos do mundo | estratos espaciais declarados dentro de um mapa — solo, subsolo, ar. São declarações de geometria e de endereçamento |
locais | lugares ou áreas nomeados — um ponto de spawn, uma zona de captura, um corredor. Um local responde onde, nunca o que acontece: não carrega lógica de jogo |
gerador de posicionamento | opcionalmente, uma regra que produz primitivas — uma quantidade, um espaçamento mínimo, uma área, um seed. Ele é resolvido quando uma versão é publicada, de forma determinística a partir do seed, e daí em diante o mapa contém primitivas, e não uma regra |
Um estrato do mundo e uma instância de mapa nunca são sinônimos.
| O que é | |
|---|---|
estrato do mundo | uma declaração dentro do mapa — solo, subsolo, ar |
instância de mapa | uma cópia em runtime independente do mapa publicado. As instâncias compartilham a mesma geometria publicada e imutável, mas têm obstáculos dinâmicos e listas de entidades independentes. Uma sala ocupa uma instância e pode selecionar estratos dentro dela |
O que vale para toda consulta.
| Sempre | O que é |
|---|---|
um único cânone geométrico | toda a geometria usa o cânone de coordenadas declarado pela plataforma, e a precisão de cada campo geométrico é declarada no próprio campo |
o modelo do mundo | é uma simplificação: a geometria do servidor não é o modelo artístico, nem precisa ser |
a resposta nomeia a instância e o momento | a consulta é respondida a partir da camada estática do mapa mais os obstáculos dinâmicos da instância consultada, e declara o momento em que é verdadeira — os obstáculos dinâmicos mudam, então a resposta é um snapshot |
os valores | são managed, e não seed: geometria não é ajuste diário, então uma edição feita pelo painel de administração é recusada, em vez de ser mantida em silêncio |
movimento e contato | não são resolvidos aqui: o mapa responde o que é o espaço. Decidir se uma posição é admissível e qual é a resposta cabe às colisões; aplicar isso ao deslocamento cabe à movimentação |
Erros
- Um mapa, uma versão ou uma instância que não existe responde not found, assim como uma versão retirada: não adianta repetir.
- Publicar geometria alterada sob uma versão existente é conflito: crie uma nova versão.
- Falhas de publicação aparecem na declaração, no deploy, nunca em runtime: um mapa acima do limite de primitivas, uma envoltória convexa acima do limite de vértices e uma malha arbitrária como obstáculo são, todos, recusas de validação antes que qualquer coisa vá ao ar.
- Uma consulta de altura fora dos limites não é erro: é a resposta declarada “fora dos limites”, e ela é distinguível de “dentro de um obstáculo”, porque num caso o cliente dá meia-volta e no outro contorna.
- Excesso na taxa de consultas responde na categoria rate limit, com prazo.
Limites
Os números chegam com o capítulo de limites da plataforma; o que acontece em cada teto já está definido.
- Primitivas de obstáculo por mapa, vértices da envoltória convexa, resolução do campo de alturas, tamanho dos limites, locais por mapa: o excesso em qualquer um deles é recusado na publicação, e não no momento da consulta.
- Instâncias por mapa: criar mais uma é recusado como conflito; as instâncias existentes nunca são liberadas para abrir espaço.
- Versões mantidas: a versão em descontinuação mais antiga é retirada, mas uma versão em uso por uma sala ao vivo nunca é.
- Taxa de consultas ao espaço: rate limit com prazo.