Esta página aún no está traducida: se muestra la versión en inglés.
Map
El mundo estático: límites, terreno, obstáculos y “¿dónde puede ir cada cosa?”. El modelo físico es, a propósito, mucho más simple que el visual: primitivas con una huella y una altura, capas con reglas y una única consulta de posición válida que reutilizan todos los demás módulos.
Cuándo usarlo
- Necesitas un mundo estático (límites, terreno, obstáculos) que el servidor pueda consultar, no solo renderizar.
- Las apariciones, los objetos que caen y las decoraciones tienen que quedar en lugares válidos: una sola consulta
RandomPositionbasada en reglas, sin atajos. - Las arenas deben regenerarse en cada partida: un
Seeddeclarado reproduce el mismo mapa en un reporte de bug. - Las cajas y los muros se rompen y vuelven: objetos destructibles con HP y temporizadores de reaparición.
- Los bots y los proyectiles necesitan respuestas de raycast y de línea de visión contra el conjunto de obstáculos.
- No lo necesitas si el mundo es puramente visual y ningún código del servidor pregunta dónde puede ir cada cosa.
Quién hace qué
| Actor | Qué hace en esta página |
|---|---|
schema-author | declara mapas, primitivas de obstáculo, objetos destructibles, capas y sus reglas |
room-owner | vincula un mapa a una sala (room); pide posiciones de aparición; lanza raycasts |
operator | coloca o quita obstáculos y capas desde el panel |
En resumen
arena declarada: semilla y límites, terreno, rocas, cajas que reaparecen y una capa de reglas[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 assetTodavía no está decidido cómo declarar con atributos en Go (O-1). Los ejemplos llegarán cuando se elija la forma de escribirlo.
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 y Destructible son generadores de colocación, no tiradas al azar en runtime. Un generador se resuelve cuando se publica la versión del mapa: las cuarenta rocas se convierten en cuarenta primitivas declaradas, y la versión publicada lleva las primitivas, no la regla. Por eso el mismo Seed da las mismas cuarenta rocas en la partida, en la repetición y en el reporte de bug — y los límites de geometría se verifican una sola vez, sobre ese conjunto resuelto, antes de que la versión llegue a un entorno.
La consulta que hacen todos los demás:
RandomPosition: una aparición justa sobre el suelo, lejos de los jugadores y sin repetirsevar 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),
))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.
// 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);
});El modelo
Dos capas, declaradas por personas distintas.
| Capa | Qué contiene y quién la declara |
|---|---|
estática | terreno con altura, primitivas de obstáculo, límites y ubicaciones: contenido de autor |
dinámica | obstáculos que aportan las entidades en runtime: puertas, objetos destructibles, plataformas. Por eso un objeto destructible es una entidad con ciclo de vida, estados y dueño, y solo pasa a ser parte del mapa en lo que aporta como obstáculo: una roca estática se declara en el mapa; una puerta es una entidad que aporta uno. Estos obstáculos no tienen ciclo de vida propio aquí: el ciclo de vida es de la entidad |
Qué declara un mapa.
| Declara | Qué es |
|---|---|
key y version | un mapa es contenido de autor: se declara en código, se identifica por key y tiene versiones; la versión es parte de lo que referencia una sala. Cambiar la geometría de una versión ya lanzada está prohibido; una edición es una versión nueva |
terreno | un campo de alturas: una cuadrícula regular con un paso declarado, y ese paso es un límite de precisión declarado, así que una consulta de altura responde según él y no con exactitud. El terreno puede no existir: una arena en el vacío es válida |
obstáculos | un conjunto cerrado de primitivas: caja, esfera, cápsula, envolvente convexa con un límite de vértices declarado. Una malla de triángulos arbitraria no se acepta, y esa es la condición para que una verificación del lado del servidor sea posible |
tipo de transitabilidad por obstáculo | intransitable · transitable para una clase declarada · solo bloquea la línea de visión. Una misma primitiva sirve como muro y como arbusto, y la diferencia se declara en vez de modelarse dos veces |
límites | el volumen fuera del cual una posición no es admisible |
estratos del mundo | estratos espaciales declarados dentro de un mapa: suelo, subsuelo, aire. Son declaraciones de geometría y de direccionamiento |
ubicaciones | lugares o áreas con nombre: un punto de aparición, una zona de captura, un pasillo. Una ubicación responde dónde, nunca qué pasa: no lleva lógica de juego |
generador de colocación | opcionalmente, una regla que produce primitivas: una cantidad, una separación mínima, un área, una semilla. Se resuelve al publicar una versión, de forma determinista según la semilla, y desde ese momento el mapa contiene primitivas y no una regla |
Un estrato del mundo y una instancia de mapa nunca son sinónimos.
| Qué es | |
|---|---|
estrato del mundo | una declaración dentro del mapa: suelo, subsuelo, aire |
instancia de mapa | una copia en runtime independiente del mapa publicado. Las instancias comparten la geometría publicada, que es inmutable, y tienen obstáculos dinámicos y listas de entidades independientes. Una sala ocupa una instancia y puede elegir estratos dentro de ella |
Qué se cumple en toda consulta.
| Siempre | Qué es |
|---|---|
un único canon geométrico | toda la geometría usa el canon de coordenadas declarado de la plataforma, y la precisión de cada campo (field) geométrico se declara en el propio campo |
el modelo del mundo | es una simplificación: la geometría del servidor no es el modelo artístico, ni tiene por qué serlo |
una respuesta nombra su instancia y su momento | una consulta se responde con la capa estática del mapa más los obstáculos dinámicos de la instancia por la que se preguntó, y declara el momento en el que es cierta: los obstáculos dinámicos cambian, así que la respuesta es un snapshot |
los valores | son managed, no seed: la geometría no se ajusta a diario, así que una edición desde la consola de administración se rechaza en lugar de guardarse sin avisar |
el movimiento y el contacto | no se resuelven aquí: esto responde qué es el espacio; si una posición es admisible y cuál es la respuesta le corresponde a las colisiones, y aplicarla, al desplazamiento |
Errores
- Un mapa, una versión o una instancia que no se encuentra responde not found, y lo mismo una versión retirada: no tiene sentido repetir.
- Publicar geometría modificada bajo una versión existente es un conflicto: crea una versión nueva.
- Las fallas de publicación aparecen al declarar o al desplegar, nunca en runtime: un mapa por encima del límite de primitivas, una envolvente convexa por encima de su límite de vértices y una malla arbitraria como obstáculo son todos rechazos de validación antes de que se publique nada.
- Una consulta de altura fuera de los límites no es un error: es la respuesta declarada “fuera de los límites”, y se distingue de “dentro de un obstáculo”, porque en un caso el cliente se da vuelta y en el otro lo rodea.
- Superar la frecuencia de consultas responde en la categoría de límite de frecuencia, con un plazo.
Límites
Las cifras llegarán con el capítulo de límites de la plataforma; lo que pasa en cada tope ya está definido.
- Primitivas de obstáculo por mapa, vértices de la envolvente convexa, resolución del campo de alturas, tamaño de los límites, ubicaciones por mapa: todos se rechazan al publicar, no al consultar.
- Instancias por mapa: crear otra se rechaza como conflicto; las instancias existentes nunca se liberan para hacer lugar.
- Versiones conservadas: se retira la versión obsoleta más antigua, y nunca una versión que usa una sala en vivo.
- La frecuencia de consultas al espacio: un límite de frecuencia con un plazo.