Saltar al contenido principal

Multijugador

Deja que varias personas compartan la misma escena a la vez. Envía mensajes, comparte valores, crea objetos para todos y muestra a los demás jugadores moviéndose con suavidad.

Estas llamadas solo funcionan cuando el multijugador está activado en tu proyecto y hay una sala abierta. El resto del tiempo no hacen nada. Así, el mismo script también funciona en una vista previa para un solo jugador, y no necesitas dos versiones.

Quién está en la sala​

ctx.net.id;        // el id de este participante
ctx.net.peers(); // todos los que están ahora en la sala
ctx.net.onJoin((peer) => {});
ctx.net.onLeave((peer) => {});

Qué se sincroniza solo​

Solo las posiciones de los cuerpos físicos marcados como shared. Todo lo demás lo envías tú.

Es a propósito. Una caja, una puerta o una pelota deben ser un único objeto que todos ven en el mismo sitio. Un personaje del jugador no debe ser compartido: si lo es, cuando una persona camina, se mueven los avatares de todos. → propiedad

Mensajes​

Usa mensajes para las cosas que ocurren: alguien ha marcado un punto, ha empezado una ronda, se ha abierto una puerta.

ctx.net.send('score', { points: 10 });
ctx.net.on('score', ({ from, data }) => {
/* … */
});

Un mensaje llega a todos menos a ti. No recibes ninguna confirmación.

Estado compartido​

Usa el estado compartido para los valores en los que todos tienen que coincidir. Es un mapa sencillo, y cada uno recibe una copia. Si dos personas escriben la misma clave, gana la última escritura.

ctx.net.state.set(ctx.net.id, { name, colour, ready: true });
ctx.net.state.get(somePeerId);
ctx.net.state.all();
ctx.net.state.on(ctx.net.id, (value) => {});

Para guardar valores de cada jugador, usa ctx.net.id como clave. Cada persona escribe su propia entrada y lee las de los demás.

Crea objetos para todos​

const id = ctx.net.spawn(props.bullet, { position, rotation });
ctx.net.despawn(id);

Recibes el id al momento, pero el objeto aparece un instante después. El id es el mismo para todos.

Solo la persona que ha creado un objeto puede eliminarlo. Cuando alguien sale de la sala, los objetos que ha creado también se eliminan.

Mueve a los demás jugadores con suavidad​

Aquí es donde más a menudo fallan las cosas, así que hay una llamada especial para ello.

ctx.net.follow(otherPlayerObject, { position, rotation });
ctx.net.unfollow(otherPlayerObject);

Llama a follow con cada posición que recibas. Entre diez y veinte veces por segundo es lo normal. Después, el objeto se mueve con suavidad, un poco por detrás de la última posición.

Volver a llamar a follow con la misma posición no cuesta nada. Así que puedes llamarlo en cada fotograma con la última posición que tengas.

No escribas las posiciones recibidas directamente en el transform

Las actualizaciones llegan con mucha menos frecuencia que los fotogramas, así que el objeto se queda quieto y luego salta: parece que los demás jugadores avanzan a saltos en lugar de caminar. Acercarse poco a poco a la última posición tampoco lo arregla. Entre una actualización y otra no hay nada nuevo hacia donde moverse, así que el objeto se para y luego da un tirón.

Una configuración que funciona​

Si empiezas desde cero, esta configuración te servirá para mucho:

  • Cada jugador controla su propio personaje: un cuerpo local que se mueve con su entrada.
  • Su posición se envía a los demás con net.state o con mensajes, entre diez y veinte veces por segundo.
  • Los personajes de los demás se mueven con follow.
  • Los objetos del mundo son cuerpos compartidos, así que la física los mantiene sincronizados por ti.
  • La puntuación y el estado de la ronda están en net.state, y los escribe quien esté a cargo de ese evento.

Siguiente: Solución de problemas: qué hacer cuando algo no funciona.