Esta página aún no está traducida: se muestra la versión en inglés.
Visibility
Con 40 jugadores, un snapshot de toda la sala funciona. Con 200, no. Una zona de visibilidad decide quién recibe qué, como un predicado declarado y no como un interruptor que activas objeto por objeto. La difusión y los paquetes por actor son dos modos de entrega declarados de un mismo modelo, así que pasar de uno a otro es cuestión de configuración, no de reescribir código. Es una optimización del canal y no un permiso; para eso, consulta Access & Roles.
Un mismo modelo declarado (el predicado, las capas, los niveles de detalle) se lee de dos maneras:
| Difusión | Paquetes por actor | |
|---|---|---|
| Envía | toda la sala (room), a todos | a cada jugador (player), solo la parte que eligen sus reglas |
| Conviene para | una sala pequeña; es el modo predeterminado | una multitud, donde el tamaño del paquete tiene que seguir siendo predecible |
| Lee la declaración | una vez, para la sala | por cada actor |
Lo que no debe filtrarse no está en el paquete, en lugar de estar oculto en el cliente: nunca se envía, y por eso es una propiedad de seguridad y no de ancho de banda.
Cuándo usarlo
- Tus salas ya no caben en una difusión de toda la sala: 200 jugadores necesitan flujos de su entorno cercano por cliente, no cada delta.
- El estado no debe filtrarse: la niebla de guerra y los campos (field) que solo ve el dueño nunca deben enviarse, en vez de ocultarse en el cliente.
- Varias sesiones comparten un mapa y no deben verse entre sí: una capa es un predicado más.
- El tamaño del paquete tiene que ser predecible en una multitud: limita los objetos y declara el orden, para que “los N más cercanos” sea una promesa y no un accidente de la densidad.
- Un jugador en un límite tiene que ver del otro lado: declara qué áreas vecinas son visibles, porque de forma predeterminada solo lo es la suya.
- No lo necesitas si la sala es pequeña. El modo de entrega con paquete compartido ya lo resuelve.
Quién hace qué
| Actor | Qué hace en esta página |
|---|---|
schema-author | declara el predicado de visibilidad, el límite de objetos y su orden, qué áreas vecinas son visibles y el modo de entrega |
any | se suscribe y recibe lo que la zona admite; puede bajar el límite de objetos para sí mismo dentro de los márgenes declarados |
En resumen
Tank; Ammo, limitado a su dueño junto al campo[Entity("tank")]
[Visible(Radius = 60)] // spatial
[Visible(Rule.SameLayer)] // layers of one map
public class Tank
{
[Sync] public Vector3 Position;
[Sync(To = Scope.Owner)] public int Ammo; // per-field scope
}@Entity('tank')
@Visible({ radius: 60 }) // spatial
@Visible(Rule.SameLayer) // layers of one map
export class Tank {
@Sync() position!: Vector3;
@Sync({ to: Scope.Owner }) ammo = 0; // per-field scope
}@entity("tank")
@visible(radius=60) # spatial
@visible(Rule.SAME_LAYER) # layers of one map
class Tank:
position: Vector3 = sync()
ammo: int = sync(to=Scope.OWNER) # per-field scopeTodavía no está decidido cómo declarar con atributos en Go (O-1). Los ejemplos llegarán cuando se elija la forma de escribirlo.
// multi-entry values are one quoted list (a specifier value is a single token)
UCLASS(PSEntity = "tank",
PSVisible = "radius:60, rule:SameMapInstance") // spatial + instances of one map
class UTank : public UObject
{
GENERATED_BODY()
UPROPERTY(PSSync) FVector3f Position;
UPROPERTY(PSSync = (To = "Owner")) int32 Ammo; // per-field scope
};
// declarations compile into the same pushed model — playserv push from the UE project or CI[Entity("tank")]
[Visible(Radius = 60)] // spatial
[Visible(Rule.SameLayer)] // layers of one map
public class Tank
{
[Sync] public Vector3 Position;
[Sync(To = Scope.Owner)] public int Ammo; // per-field scope
}El modelo
Qué declara una regla de visibilidad.
| Declara | Qué es |
|---|---|
predicado | la regla en sí, escrita en el mismo lenguaje de predicados que los predicados de acceso y las condiciones de transición. Un radio, una instancia de mapa, un equipo y la propiedad de un objeto son casos particulares de un predicado, no mecanismos aparte: en el contrato hay exactamente un lenguaje así |
límite de objetos y su orden | una regla puede limitar la cantidad de objetos, y entonces el orden de selección se declara, no se deduce: “los N más cercanos” es un predicado más un ordenamiento por distancia más un límite. Un predicado solo no puede expresarlo, porque responde “¿esta fila califica?”, no “¿cuál de las que califican está más cerca?” |
áreas vecinas | si los objetos de una sala o instancia de mapa vecina son visibles, y cuáles exactamente. Nunca es implícito: sin declaración, el área es aquella donde está el destinatario |
modo de entrega | paquete compartido: lo mismo para todos, barato en CPU. paquete por actor: cada receptor recibe el suyo, según su zona; caro en CPU e imprescindible con poblaciones grandes |
Qué se cumple en toda zona.
| Siempre | Qué es |
|---|---|
visibilidad | no es un permiso: lo que la zona oculta puede estar disponible por permiso, y al revés (ver abajo) |
el destinatario | puede bajar el límite: dentro del máximo declarado y nunca por debajo del mínimo declarado, porque un predicado es el mismo para todos aquellos cuyo contexto coincidió, mientras que el tamaño del paquete es problema del destinatario |
truncamiento | es observable: el destinatario se entera de que el paquete se cortó y con qué orden. El truncamiento silencioso está prohibido, porque no se distingue de que ya no haya más objetos |
degradación | se declara: cuando se agota el presupuesto para armar paquetes por actor, la plataforma vuelve al paquete compartido tal como está declarado, en lugar de empezar a perder destinatarios al azar |
forma del paquete | es una promesa débil: el tamaño y la composición de un paquete no deberían permitir deducir que existen objetos ocultos |
La visibilidad no es un permiso
La zona es una optimización del canal, no un control de acceso. No los mezcles: una configuración de niebla de guerra ampliaría los derechos sin avisar, o los derechos empezarían a depender de la distancia. El tamaño del paquete puede insinuar que existen objetos ocultos, así que, donde su existencia no deba filtrarse, usa los permisos de Access & Roles, no la zona.
“¿Quién ve esto?” y “¿qué ve?” se pueden consultar. El costo de los paquetes por actor es una lectura de primera clase, en el código y en el panel.
Errores
- Un destino de suscripción no declarado es un rechazo de validación.
- La falta de permiso para suscribirse responde forbidden o not found según si la existencia del destino es secreta: el propio rechazo no debe revelar lo que rechaza.
- Una posición de reanudación que no se puede interpretar es una solicitud incorrecta, no un reinicio silencioso desde el momento actual.
- Una suscripción que cerró la plataforma y una cantidad de suscripciones agotada son, ambas, conflictos.
- Ampliar una vista es
fn. Otorgar una vista ampliada y fijar niveles de detalle se rechazan con forbidden para una sesión de jugador, y su vista no cambia: un cliente espectador no puede ampliar sus propios permisos otorgados (grant). - Una instancia que la vista del llamador excluye responde
not found, la misma respuesta que una que no existe: un forbidden confirmaría que hay algo detrás del muro. - Leer el costo de los paquetes por actor es
fnadm: una función en la nube o el panel, nunca un cliente.
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.
- El costo de un paquete por actor: al agotarse, degradación declarada al paquete compartido con un aviso, nunca una pérdida arbitraria de destinatarios.
- Objetos por regla: limitados, con un orden declarado y un indicador de truncamiento observable.
- Suscripciones por actor: una nueva se rechaza y las existentes siguen.
- Tamaño de la delta: la delta se divide, no se trunca, y la división es observable.
- La tasa de envío: un límite superior, no una garantía.