Noticias

¡RECUERDA QUE SI ERES UN NUEVO USUARIO, DEBES PRESENTARTE PARA PODER PUBLICAR MENSAJES! | TENEMOS CANAL OFICIAL DE TELEGRAM: t.me/unity3dspain

P1 - UNET [Networking] - Primero Pasos

Iniciado por francoe1, Enero 29, 2016, 08:54:08 PM

Tema anterior - Siguiente tema
Enero 29, 2016, 08:54:08 PM Ultima modificación: Febrero 04, 2016, 06:59:17 PM por francoe1
¡Buenas a Todos!
¡Breve reflexión, resumen y crítica!Este topic lo creo con la intención de beneficiarnos todos en la programacion de Networking sobre UNET, si bien la herramienta nos da el título de "Facil implementacion" todos los que hayan experimentado se habrán dado cuenta, que a pesar de las fallas que aun tiene, su implementacion no es tan sencilla. Lo que los desarrolladores de UNET quisieron decirnos es que es más sencillo que RakNet o programar sobre Socket. [/quote]Para Empezar necesitamos una version 5 de Unity3D (Mejor si es la Última), conocimiento en programacion C#, breve idea de cómo funcionan Servidores Autoritativos.Primero Pasos1- Empecemos por crear un objeto vacío en la escena y agregamos el componente de NetworkManager y NetworkManagerHud.
2- Crear un Script en C# asignar el nombre de PlayerSetup (Opcional) agregar la librería UnityEngine.Networking y la clase PlayerSetup que herede de NetworkBehaviour.
3- Empezar con la Programacion del Movimiento:
    A- Programar un movimiento, simple sin fisicas.
private void Movement()
{
    Vector3 Direction = new Vector3(Input.GetAxisRaw("Horizontal"),0,Input.GetAxisRaw("Vertical"));
    Direction = transform.TransformDirection(Direction);
    Vector3 NextPosition = transform.position + (Direction * Time.deltaTime * 5);
   
    transform.position = NextPosition;
}
     B- Para llamar a esta función debemos primero comprobar si somos el Jugador Local (http://docs.unity3d.com/ScriptReference/Networking.NetworkBehaviour-isLocalPlayer.html">isLocalPlayer).
     C- Volvemos a la escena donde teníamos nuestro NetworkManager creamos un cubo y le asignamos nuestro componente PlayerSetup, automáticamente se añadirá junto a este otro componente llamada NetworkIdentity, en el debemos seleccionar la opción LocalPlayerAuthority creamos un prefabs del cubo y lo borramos de la escena.
     D- Nos dirigimos al componente NetworkManager, vamos a donde dice SpawnInfo y en el lugar de PlayerPrefab asignamos el que creamos anteriormente.
     E- Volvemos al Script PlayerSetup y desde la función Update ahora podemos llamar a nuestra función Movement, antes comprobando si es el Player Autorizado.
public void Update()
{
    if(!isLocalPlayer)
    {
        //CLIENTE NO LOCAL
        return; //Si no es el jugador termina la ejecución de Update
    }
    else
    {
        //CLIENTE LOCAL
        Movement();
    }
}
4- ¡Excelente!, Ahora si compilamos para Windows podremos ver que el cubo se mueve en ambas ejecuciones, pero nos daremos cuenta de que el Jugador 1 no podrá ver el movimiento del Jugador 2Sincronizando el movimiento1- Para sincronizar el movimiento en red se utiliza una técnica llamada predicción de la posicion, esto quiere decir que mientras nos movemos de manera local el servidor intercepta multiples actualizaciones de nuestra posicion pero como el movimiento no va a ir por un canal seguro, podría perderse un paquete o simplemente el Ping sea muy alto y los clientes no locales experimentarian un movimiento extraño en los demás clientes.¿Cómo creamos una sincronización?    A- Para sincronizar debemos enviar los datos al servidor, gracias a UNET podemos utilizar SyncVar y Command para hacer este trabajo mucho más simple que el conocido "Serialize and Deserialize" de paquetes. Para empezar necesitamos crear una variable privada tipo Vector3 donde almacenamos nuestra posicion, y una función de tipo void con los atributos de Command
      ¿Qué son los Command? Son funciones que se encuentran del lado del Cliente pero siempre se ejecutan en el servidor.
      ¿Que el SyncVar? SyncVar nos sirve para que una variable esté sincronizada para todos los Cliente. 
      ¡A tener en cuenta! Si nosotros cambiamos una variable de forma local, sin avisarle al servidor, los demás clientes no estarán enterados de este cambio, para que un SyncVar funciones esta debe ser modificada por el servidor, y este mismo se encarga de actualizar el valor en todas las instancias de cliente.  Veamos el Código
[SyncVar]
private Vector3 SyncPosition;

[Command]
private void Cmd_SendPosition(Vector3 Pos)
{
    SyncPosition = Pos;
}
2- Ya tenemos nuestro sistema para Sincronizar la posicion de nuestro jugador, ahora vamos a ponerlo en marcha, aun nos faltan 2 pasos muy importantes, al cliente local no le interesa el valor de SyncPosition, ya que este no depende de tal variable para su movimiento, pero no obstante los otros clientes no locales van a tomar ese dato para ubicarte en su espacio local. ¿Cómo hacemos esto?, vimos que nuestra función Update está separada en dos partes, la primera para los clientes NO LOCALES y la segunda es solo para clientes LOCALES, quiere decir que vamos a utilizar la parte no local para sincronizar nuestro movimiento en los demás clientes.

    A-Vamos a enviar la informacion de nuestra posicion al servidor utilizando el comando Cmd_SendPosition(), esto lo realizamos desde nuestra función Movement();
Cmd_SendPosition(NextPosition);  
    B- Seguido a esto, nos dirigimos a nuestra función Update en la parte no local y creamos un movimiento Suave entra la posicion actual del Player no local y la de la variable Sincronizada
transform.position = Vector3.MoveTowars(transform.position,SyncPosition, Time.deltaTime * 15);
    C- Por Último Compilamos nuestro proyecto y veremos como el movimiento se encuentra sincronizado en ambos clientes.
El Código debe quedar de la siguiente manera
public void Update()
{
    if(!isLocalPlayer)
    {
        //CLIENTE NO LOCAL

        transform.position = Vector3.MoveTowars(transform.position,SyncPosition, Time.deltaTime * 15); // Movimiento del Jugador en ambiente no local
        return; //Si no es el jugador termina la ejecución de Update
    }
    else
    {
        //CLIENTE LOCAL
        Movement();
    }
}

[SyncVar]
private Vector3 SyncPosition;

[Command]
private void Cmd_SendPosition(Vector3 Pos)
{
    SyncPosition = Pos;
}

private void Movement()
{
    Vector3 Direction = new Vector3(Input.GetAxisRaw("Horizontal"),0,Input.GetAxisRaw("Vertical"));
    Direction = transform.TransformDirection(Direction);
    Vector3 NextPosition = transform.position + (Direction * Time.deltaTime * 5);
   

    Cmd_SendPosition(NextPosition);//Enviar información al Servidor.
 
    transform.position = NextPosition;
}
Bueno, eso es todo por hoy, el material es escrito para tratar de explicar mejor las cosas.Siguientes
Sistema de Puntuaje + UNET + Simple UI
Sistema de Salud + UNET + Simple UI
Explicación más detalladas de Command
Sistema de Disparos + UNET + Simple UI

VIDEO TUTORIAL de todo lo explicado
Como dije al comienzo, espero que esto no sea solo un aporte de mi parte, si no que todos los que sepan y quieran aportar vayan anexando sus conocimiento, prácticas y ejemplos para poder entender mejor cómo armar nuestro propio juego en red..

PD: El post lo escribí todo desde la WEB pueden existir errores en la Sintaxis de la programacion. NO SE OLVIDEN DE PASAR POR MI CANAL DE YOUTUBE, DONDE SUBO TUTORIALES SOBRE UNITY
">IR AL CANAL [/quote]¡SALUDOS A TODOS y SUERTE! 

Etiquetas: