
https://connect.unity.com/p/spriteanimator-2d-tool
Completo sistema para trabajar con Sprite Sheets
Visitar en Assets Store
https://assetstore.unity.com/packages/tools/sprite-management/spriteanimator-153405
Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.
Mostrar Mensajes Menú
using UnityEngine;Como veras se maneja por Eventos, estos son muy descriptivos con sus propios nombre.1- Para crear el Timer utilizamos la siguiente función Timer.Singletone.QuickTimer(TiempoDeEspera,AutoRepeticion,GestionManual);2- Utilizamos la Funcion Start para dar inicio al Contador.3- Si deseamos terminar con el contador antes de que este finalice utilizamos Stop.4- Para limpiar todos los contadores utilizar Timer.Singletone.ClearAll().5- Para detener todos los contadores utilizar Timer.Singletone.StopAll(). Existen algunas cositas mas, esta completamente en Español podes guiarte muy fácilmente. ¡Saludos!
using System.Collections;
using CustomTool;
public class Weapon : MonoBehaviour
{
private TimerItem _timerReload;
private int _cadence = 1;
private float _tmpCadence = 0;
private void Start()
{
_timerReload = Timer.Singletone.QuickTimer (1, false, true);
ReloadEventSetup ();
}
private void Update()
{
if(Input.GetKeyDown(KeyCode.R))
{
_timerReload.Start ();
}
if (Input.GetMouseButton (0) && !_timerReload.IsRuning)
{
if (_checkCadence)
{
Shot ();
}
}
}
private bool _checkCadence{get{ if(_tmpCadence < Time.time){ _tmpCadence = _cadence + Time.time; return true; } else return false; }}
public virtual void Shot()
{
print ("shoting");
}
public virtual void Reload()
{
print ("Finish Reload");
}
private void ReloadEventSetup()
{
_timerReload.EventStart += () =>
{
print ("start reloading");
};
_timerReload.EventFinish += () =>
{
Reload();
};
_timerReload.EventStop += () =>
{
};
}
}
private void Shot()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.
{
Ray = Camera.Look;
RaycastHit Hit;
if(Raycast out Hit)
{
if(Hit == "Enemy")
{
Ejecuta Accion
}
}
}
public void Shot()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
{
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;
}
}
public const int MaxHealt = 100;bien con esto ya tendríamos nuestro Sistema de salud casi terminado, pero debemos tener algunas cosas en cuenta.
[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);
}
void Update()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:
{
if(Healt <= 0)
{
IsDeath = true;
}
}
[SyncVar]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.
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();
}
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;
}
[SyncVar]Con esto ya tenemos nuestro sistema de puntuación funcionando, ahora debemos gestionarlo, vamos a crear una función OnGUI para visualizar los datos de todos lo Clientes conectados.
public string Name;
[SyncVar]
public int Kills;
[SyncVar]
public int Deaths;
[SyncVar]
public int Score;
public void SetName(string value)
{
Name = value;
Cmd_SetName(value);
}
public void AddKill()
{
Kills++;
Cmd_AddKill(Kills);
}
public void AddDeath()
{
Deaths++;
Cmd_AddDeath(Deaths);
}
public void AddScore(int value)
{
Score += value;
Cmd_AddKill(Score);
}
[Command]
private void Cmd_SetName(string value)
{
if(!isServer)return;
Name = value;
}
[Command]
private void Cmd_AddKill(int value)
{
if(!isServer)return;
Kills = value;
}
[Command]
private void Cmd_AddDeath(int value)
{
if(!isServer)return;
Deaths = value;
}
[Command]
private void Cmd_AddScore(int value)
{
if(!isServer)return;
Score = value;
}
void OnGUI()Bien, ahora podemos hacer nuestro test utilizando Inputs y la función Update
{
foreach(PlayerInfo current in GameObject.FindObjectsOfType<PlayerInfo>())
{
if(current == this)GUI.color = Color.red;
GUILayout.Box(current.Name + " D [" + current.Deaths + "] K [" + current.Kills + "] S [ " + current.Score + "]" );
}
}
void Update()FIN DE LA SEGUNDA PARTE Siguientes
{
if(!isLocalPlayer)return; // Si no es el jugador Local Sale de la funcion UPDATE
if(Input.GetMouseButtonDown(0))AddScore(100);
if(Input.GetMouseButtonDown(1))AddKill();
if(Input.GetMouseButtonDown(2))AddDeath();
}
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
¡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()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).
{
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;
}
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()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
{
if(!isLocalPlayer)
{
//CLIENTE NO LOCAL
return; //Si no es el jugador termina la ejecución de Update
}
else
{
//CLIENTE LOCAL
Movement();
}
}
¿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]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.
private Vector3 SyncPosition;
[Command]
private void Cmd_SendPosition(Vector3 Pos)
{
SyncPosition = Pos;
}
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 Sincronizadatransform.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 manerapublic void Update()Bueno, eso es todo por hoy, el material es escrito para tratar de explicar mejor las cosas.Siguientes
{
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;
}
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 explicadoComo 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
Si necesitas una herramienta de joystick virtual para tu proyecto de plataforma móvil, seguro esta es la opción más rápida y sencilla que podrás encontrar.
Características:
* Simple Implementación.
* Optimización para correcto funcionamiento en cualquier móvil.
* Posibilidad de cambiar de Joystick Físico a Virtual con un Click.
* Scripting Sencillo.
* Totalmente Configurable.
* Múltiples Joystick, Sin Límites.
Implementación:
1- Abrir el UnityPackage descomprimirlo en nuestro Proyecto de Unity3D.
2- Crear Canvas en nuestra Escena.
3- Veremos que en el Menú superior aparecerá una nueva solapa llamada 'Control', accediendo a esta tenemos una única opción Joystick, la seleccionamos.
4- Aparece una ventana con las Opciones para la Configuración Grafica el Fondo y la Palanca (Pad and Handle).
5- Presionar Guardar, y ya tienes tu Joystick Virtual listo para utilizar.Hay un Script de Prueba para que vean cómo Funciona. Es muy simple.
http://unityspain.com/applications/core/interface/file/attachment.php?id=8991">Joystick Franco.unitypackage
.. Gracias
