Jump to content
UnitySpain

Search the Community

Showing results for tags 'unet'.



More search options

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • Inicio
    • Proyectos
    • Offtopic
    • Unity Feeds
    • Website
  • Mesa de ayuda
    • Unity
    • Arte
    • Otras Especialidades
    • Builds & Dispositivos
  • Aportes de la Comunidad
    • Recursos
    • Eventos
    • Buenas Prácticas
  • Bolsa de trabajo & Colaboraciones
    • Ofertas y Demandas
  • Post Antiguos
    • General (Antiguo)

Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


Especialidad

Found 10 results

  1. Buenas a todos. Hace ya unas semanitas que estoy aprendiendo uNet, pero me surge una duda con objectos se se puede droppear (soltar en el mapa) y pickup (se pueden recoger del suelo por cualquier usuario). Ahora mismo lo tengo funcionando bien, un player se encuentra un item, lo recoge y lo añade a su inventario, luego lo suelta y aparece en el mapa, otro player ve ese objeto y lo puede recoger. La cosa es que no se si lo tengo bien estructurado en cuanto a Commands y ClientRPCs, pongo un ejemplo inventado y en bruto para que veais como lo tengo: "Al hacer click en un item, ejecuta la funcion de "Añadir Item al inventario" y la esctructura de la funciona es la siguiente:" .... .... if (isItem == true) { CmdAddItem(); } [Command] void CmdAddItem() { //añadir item a una lista //modificar el nombre a item.name //modificar parent del item //añadir item a un Slot //indicarle al item en que slot esta //...y mas logica RpcAddItemInform(); } [ClientRPC] void RpcAddItemInform() { if(isLocalPlayer) { //añadir item a una lista //modificar el nombre a item.name //modificar parent del item //añadir item a un Slot //indicarle al item en que slot esta //...y mas logica } if(!isLocalPlayer) { //modificar el nombre a item.name //modificar parent del item //indicarle al item en que slot esta //...y mas logica } } Este código es muy bruto es solo para ejemplificar lo que me esta ocurriendo con todo lo que tengo que sincronizar entre servidor y clientes. Como veis, tanto lo que ejecuto en el Command como en el RPC para el LocalPlayer, como en el RPC para el NoLocalPlayer, se repiten las lineas de la lógica, con variantes ya que cada cliente tiene que saber lo que que tiene que saber, pero encuentro absurdo tanto repetir código. Primero en el Command le doy toda la logica ya que es el server y lo tiene que saber todo o casi todo, luego ejecuto el RPC para actualizar los clientes pero con variantes según si es el playerlocal o no es el local. Parece una tontería pero al tener ya varios Command y RPCs en el código veo muchas lineas de Lógica repetidas y tampoco acabo de ver el sentido a actualizar la información del Item en el servidor si luego al informar a los clientes les paso el mismo código a mano, al ejecutar el RPC no debería "Copiar" lo que hay en el server? En mi opinión estoy haciendo algo mal en terminos de organizacion de donde ejecutar las lineas de logica, donde ejecutar las lineas de comprobación previas a la lógica (como por ejemplo saber si tengo un Slot libre en el inventario antes de añadir el item). He buscado mucho por internet pero a parte de la poca info practica, la gente lo hace de distinta manera. Alguien podria arrojar algo de luz para ver como se suele estructurar las sincronizaciones servidor-cliente y que el server sea autoritativo? Un ejemplo en bruto como el mio seria genial. Saludos!!
  2. Buenas a todos, os comento: Soy programador nivel intermedio avanzado y con escaso conocimiento de redes, me he leído la documentación de unity y hay cosas que creo que no he llegado a comprender del todo bien. Estoy utilizando el código de unity para montarme un juego multijugador en el que un jugador hace de host y he seguido un par de tutos y como ya he comentado con la información de la pagina. Problema: A la hora de disparar y moverse el cliente no spawnea la bala en la posición correcta sino unos centímetros a la derecha o izquierda depende en que sentido se mueva. Esto en el que hace de host no pasa como es de esperar. Estoy utilizando una funcion con command y le paso como parámetros posición velocidad y rotación de la bala la spawneo y la envió con networkServer.spawn a todos. Como ya he comentado esto hace que el cliente reciba la bala tarde si se esta moviendo, puedo llegar a entender que al serializar los datos y enviarlos por red haya cierto delay, pero si lo estoy probando en mi ordenador debería de ser cero y no lo es ademas de que unos centímetros tienen demasiada repercusión en la jugabilidad. He cambiado de canal el script del disparo (disparo y andar no están en el mismo script aunque no creo que importe) y sigue estando el problema, tambien he hecho un monton de pruebas sin exito. Alguno sabe si hay alguna forma de reducir eso? como se hace en la realidad? Estaría muy agradecido con cualquier ayuda. Adjunto el código, es código de testeo, nada depurado: using UnityEngine; using UnityEngine.Networking; //[NetworkSettings(channel = 1)] public class Disparo : NetworkBehaviour { //Animaciones public bool SacarGuardar; //Disparo public Rigidbody Bala; public Transform SpawnBala; public int VelocidadBala; //Velocidad movimiento jugador public Rigidbody m_Rigidbody; // Use this for initialization void Start () { m_Rigidbody = GetComponent<Rigidbody>(); } // Update is called once per frame [ClientCallback] void Update () { if (!isLocalPlayer) { return; } SacarGuardar = Input.GetButton("Fire2") ? true : SacarGuardar; if (SacarGuardar == true) if (Input.GetButtonDown("Fire1")) { CmdSpawnBalaNew(m_Rigidbody.velocity, VelocidadBala, SpawnBala.forward, SpawnBala.position, SpawnBala.rotation); } } [Command] void CmdSpawnBalaNew(Vector3 rigidbodyVelocity,float velocidadb, Vector3 forward, Vector3 position, Quaternion rotation) { Rigidbody bullet = Instantiate(Bala, position, rotation) as Rigidbody; Vector3 velocity = rigidbodyVelocity + velocidadb * forward; bullet.velocity = velocity; NetworkServer.Spawn(bullet.gameObject); //(bullet.gameObject, 4.0f); } }
  3. Hola, resulta que en mi juego en el modo multijugador no van sincronizados los objetos a lo que me refiero es que en una pantalla va mas la plataforma mas adelante mientras que en la otra va mas atras o si en una pantalla activo algo lo cual desaparece una plataforma en una desaparece y en la otra no. En la de laplataforma en movimiento le puse un network transform pero en la del host se ve bien mientras que en la del cliente va a tirones como si fuera con lag, no se si existira un sincronozado de manera global o si es en caso de que sea objeto por objeto que en ambas patallas el movimiento fuera el mismo y no retardado o a tirones. Gracias de antemano.
  4. Muy buenas gente, tengo una consulta para aquellos que hayan trabajado o hayan usado por curiosidad el UNET de Unity para hacer juegos online. Mi consulta, es la siguiente: ¿Cómo puedo enviar un comando desde un cliente ajeno al servidor? Me explico mejor, tengo un Player, que es el cliente. El cliente se llama Player y el script es Movement. Este tiene un collider que al tocar un objeto llama al comando que está en el servidor, pero no se como hacerlo. El servidor tiene un script que se llama Instancie, y esta en un objeto con el nombre de Instanciador. Este cliente tiene que mandar un comando a un Script que está en el servidor. El objeto Instancie, tiene la identidad de servidor, por lo que al entrar como cliente este objeto se deshabilita. Si pongo la identidad como local player, me dice "Trying to send command for object without authority" y no funciona el comando Spawn que tengo en el server. No se si me explico o los he mareado. Resumiendo: Tengo un player A que es el cliente, y quiero que este active el script de un objeto B que se activa con el servidor. ¿Como puedo hacerlo? El script funciona bien si uso el comando desde el Player que es el servidor, si lo uso desde el Player Cliente me dice: "Trying to send command for object without authority" Gracias de Antemano.
  5. Aparte de unet , que otras apis de terceros para crear juegos multijugador online conoceis?
  6. Bienvenidos a la cuarta entrega de UNET. En esta tratare de cubrir lo necesario para efectuar un disparo, como vimos en anteriores tutoriales logramos un movimiento, sincronizacion y sistema de salud funcional, aun que no de la mejor manera. En este tutorial vamos a necesitar utilizar Commandos. Bueno vamos al grano, para empezar debemos crear nuestro componente PlayerWeapon(Opcional), cabe destacar que cada juego tiene un GAME PLAY propio por lo tanto obviamos como funcionan los aspectos del mismo. Para poder enviar un dato, como lo necesitamos en este momento, el impacto de la bala con nuestro enemigo debemos tener los datos de nuestro enemigo, una forma muy simple de poder interactuar con otro jugadores es obteniendo su ID de red. Suponiendo que tenemos nuestro sistema de Armas con el método Raycast ya listo, nos daremos cuenta que siempre obtenemos un dato de las colisiones para frente a este seguir diferentes acciones. EJ: private void Shot() { Ray = Camera.Look; RaycastHit Hit; if(Raycast out Hit) { if(Hit == "Enemy") { Ejecuta Accion } } }Por lo genera siempre es de esta manera, bueno cuando trabajamos con networking se sigue haciendo del mismo modo. y el dato que tomamos el el ID a este lo enviamos por comando, y el servidor se encarga de aplicarle el daño en este caso. public void Shot() { Codigo de Disparo por RayCast, tomamos el net id y lo enviamos por commando Cmd_TakeDamage(hit.NetID); //EJEMPLO } [Command] private void Cmd_TakeDamage(uint PlayerTake, int Damage) { //buscamos los jugadores que corresponden al ID,con una simple funcion var otherp = FindPlayer(PlayerTake); if(otherp != null) { //llamamos la funcion de Take! otherp.playerHealt.HealtTake(50); } } private void FindPlayer(uint ID) { foreach(var p in GameObject.FindObjectsOfType<PlayerControl>()) { if(p.netId.Value = ID) { return p; } } return null; } public class PlayerControl : NetworkBehaviuor { public PlayerHealt playerHealt; public override void OnStartClient() { playerHealt = GetComponent<PlayerHealt>(); } } public class PlayerHealt : NetworkBehaviuor { [SyncVar] int current = 100; [Server] internal void HealtTake(int value) { current -= value; } }De esta simple manera tendríamos ya nuestro sistema de disparo funcionando, ahora deberíamos mejorarlo para que funcione aun mejor. !Importante¡ Cuando se trata de la programación de videojuegos o aplicaciones en red uno de los temas mas importantes son los de Seguridad, cuando se trabaja con dinero real este punto se refuerza con personal altamente calificado y experimentado, quiero decir que si la idea que tienes es crear un juego Online estilo AVA u otro MFPS y aun no tienes el personal y la experiencia necesaria, entonces no lo intentes. Esta serie de Información y Tutorial es solo para lograr juegos en red simple, para poder compartir con amigos o mejor aun un simple sistema networking donde la vulnerabilidad no se un problema grave. Bueno gente, como les prometí esta es la cuarte entrega, no es el material mas detallado pero se pueden dar cuanta de la fácil implementacion que UNET nos presta en su librería de Alto Nivel para networking. Mi idea es que si alguien necesita algo mas detallado solo comente y explicare paso por paso como lograr. obvio si es que entiendo lo que necesite. No olviden visitar mi Blog! Un abrazo -. Franco
  7. Bienvenidos a otro tutorial de UNET. Como vimos en anteriores tutoriales, para poder sincronizar una variable en nuestro jugador locas debemos primero asignarla y luego enviar ese valor al servidor. EJ : (P-Local) Cambió su posicion --(Envia a traves de comando su nueva posicion al servidor)--> (SERVER) El servidor recibe estos datos y los envía a todos los Clientes. Teniendo esto en cuenta, para lograr un Sistema de Salud funcional debemos primero tener el valor de la salud actual, un evento que se llame cuando muere, 2 funciones una de daño y la otra de recuperación, y por ultimo el comando para enviar el estado de nuestra salud. Vemos... Primero creamos lo básico. public const int MaxHealt = 100; [SyncVar] public int Healt; public delegate void d_Death(); [SyncEvent] public event d_Death EventDeath; [Client] public void TakeDamage(int value) { Healt -= value; Healt = Mathf.Clamp(Healt,0,MaxHealt); } [Client] public void TakeCure(int value) { Healt += value; Healt = Mathf.Clamp(Healt,0,MaxHealt); }bien con esto ya tendríamos nuestro Sistema de salud casi terminado, pero debemos tener algunas cosas en cuenta. Jamás un jugador va a poder infringir directamente daño a otro, de esto se encarga el servidor, pero existe una problemática, cuando nosotros ejecutamos un disparo, este evento es gestionado por el servidor, entonces es el Servidor en nombre de X Cliente dueño del disparo, supongamos que este impacta con otro jugador, ¿Quien resta la salud?, La respuesta es el Servidor. Es decir, si nosotros llamamos una funciona cualquiera desde un comando estamos haciéndolo en nombre del servidor. (CLIENTE) ---> Ejecuta ---> COMMAND ---> (SERVIDOR) ---> Ejecuta Funcion ---> TakeDamage(); Dicho lo anterior, podremos darnos cuanta de que no existe interacción Cliente/Cliente por lo que esto se denomina Cliente/Servidor. ¿Cual es realmente la problemática?, Aunque existan varios problemas relacionados solo con un sistema de salud, deberíamos destacar el mas importante. El Jugador local solo debe enviar su estado, no hay que confundir, es decir, el servidor no se debe de encargar de procesar si está muerto o no, para eso creamos nuestro sistema. Vi muchos errores a la hora de implementar funciones incoherentes, por ejemplo, que todos los jugadores comprueben si la salud es menor o igual a cero entonces esta muerto. void Update() { if(Healt <= 0) { IsDeath = true; } }Esto es un grave error, porque los tiempos de sincronización pueden variar según el Ping (Tiempo de Envío y Recibo de Datos) que el Cliente y servidor tengan. vamos a dar un Ejemplo: Tenemos 4 Clientes en un servidor, Cliente 1 dispara y le quita 100 de salud al Cliente 2 Esta acción tomó un tiempo de. 1- Cliente 1 (Enviar Datos del disparo al Servidor y Retornar Resultados) : 2s 2- Cliente 2 (Recibe la noticia de que se le a impactado, el servidor llama a su función TakeDamage(), luego, el Cliente 2 envía los dato de su estado al Servidor) : 4s 3- Clientes (Servidor Actualiza el Estado del Cliente 1 en todas las instancias del juego, diciendo que el valor de Healt es cero) 1s Vemos que en el Punto 1 el Cliente 1 ya sabe que le infligió daño al Cliente 2, pero aun el Cliente 2 no se enteró, suponiendo que el primer paso Duro solo 1s, ya que el segundo añadido es el tiempo que el Servidor tardó en enviar esa información al Cliente 1, el Cliente 2, por lo tanto recibe daño, y envía el valor de Healt al servidor, 4s + 1s que el servidor toma para enviar los datos de este evento al Cliente 3, 4 es el retardo que existiría, suponiendo así, que cada instancia debería comprobar aún si el Cliente 2 está vivo, pero qué pasa si en ese lapso de 4 segundo el Cliente 2 sobrevive, es decir, un ejemplo, lo reviven estilo BF, el Cliente 1,3,4 tendrían una mala información. en destiempo. Aunque el ejemplo en cierta forma parece no tener coherencia el problema se presenta cuando múltiples clientes con distintos tiempos de respuestas se conectan al servidor, este error puede llegar a hacernos ver el jugador muerto disparando. ¿Cómo lo solucionamos? La solución en cierta parte, sería utilizar Eventos, va a seguir existiendo un tiempo de retardo, es normal, pero la información de las instancias de cada cliente va a ser más clara. [SyncVar] internal bool IsDeath; [SyncEvent] public event d_Death EventDeath; void Update() { if(!isLocalPlayer)return; if(Healt <= 0 && !IsDeath) { IsDeath = true; if(EventDeath != null)EventDeath(); Cmd_SendInfo(Healt,IsDeath); } } [Command] private void Cmd_SendInfo(int healt, bool isDeath) { Healt = healt; IsDeath = isDeath; if(IsDeath)if(EventDeath != null)EventDeath(); }De esta manera estamos enviando de una manera, quizas un poco desprolija nuestra información al servidor, pero si prestaron atención en la función Update, se agregó un condicional para saber si es el jugador local, ya que solo él, podrá gestionar su salud y avisar al servidor su estado. Hay que entender, que aunque Unet Serialize nuestros datos y los optimice podemos ayudar también nosotros, a que esta tarea sea aun mas optima, por ejemplo enviando un string formateado de una manera para guardar el valor de nuestras variables. string Data = "100/0"; [Command] private void Cmd_SendInfo(string data) { string[] values = data.Split('/'); Healt = int.Parse(values[0]); IsDeath = int.Parse(values[1])? false : true; Data = data; } de esta manera optimizamos el paquete, ya que solo enviamos un dato. Bueno eso es todo por ahora, espero les sirva. Para tener un poco más organizados mis tutoriales abrí un Blogger donde encontraran todo mi material y podrán seguir mis tutoriales de UNET. http://unitydoc.blogspot.com.ar/ Saludos
  8. ¡Buenas a Todos! 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 Pasos 1- 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 (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 2 Sincronizando el movimiento 1- 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 ¡SALUDOS A TODOS y SUERTE!
  9. Hola REbuenas, hace un par de años o mas que deje el tema de la programacion por temas laborales y hace un par de semanas mas o menos e vuelto a la intringulis de unity, ya realice algun proyecto ("SpacePoly"- "Pingu-Pedos"), ahora que vuelvo veo el unity 5.1 etc y el UNET, pero veo el foro como "parado" no se si hay otros sitio nuevo o que, pero mi sugerencia es relativa al UNET, igual que hay un apartado scripting, unity android iphone, pues crear otro con referencia al UNET por que tiene muy buena pinta la verdad y tiene mucho potencial
  10. Hola, estoy haciendo un juego de Boxeo Multijugador (Unity 5.1, UNET). Ambos personajes, usan el mismo script. Cuando uno muere, hace la animacion de muerte y el problema lo tengo cuando le tiene que avisar al servidor que se murio, y que por lo tanto el otro deberia festejar. Me esta costando entender como funciona el ClientCallback, Client y ClientRpc. Tengo dos script iguales, y uno de los dos en un momento determinado llama a un ClientCallBack. La pregunta es: En ambos personajes que tengo el script va al clientcallback simultaneamente (cuando uno de los dos va a ese clientcallback), o solo va el que lo llama... pasa que actualmente, el que llama a el clientcallback ejecuta todo bien, y hace varias algunas syncvar a travez de un command, pero el otro personaje ni se entera que las variables cambiaron. Es como que no estan syncronizando variables. El que ejecuta el clientcallback se entera del cambio de las syncvar y el otro no se entera. No se como hacer para que ambos se den cuenta.
×
×
  • Create New...