Menú

Mostrar Mensajes

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ú

Mensajes - francoe1

#361
General (Antiguo) / Asset Store [Encuesta]
Enero 08, 2018, 08:52:05 PM
Creo que el mercado de assets se divide en dos grandes rasgos, el primero es el mercado "Casual", son aquellos desarrolladores que desconocen totalmente el tema, no saben programar, diseñar, modelar, animar.. etc, y en el intento de armar algo compran pequeños assets en la tienda, por lo general buscan algo genérico que cubre múltiples secciones, assets que tengan un "Demo" de algo jugable para luego editar y poder decir "Hice un juego", esto se ve mucho con assets FPS -
 
El segundo es el mercado "Indie" Profesional/Semiprofesional, estos buscan assets que les sean de total conveniencia en el desarrollo, es decir, una persona que necesita un sistema de networking evaluaría el precio de un assets que cumpla sus requisitos con el tiempo que llevaría armar su propia librería, esto pasaria en todas las areas, pero dificilmente el apartado grafico tendria un valor "bueno" en este contexto debido a que este es el corazón del juego, como @lightbug comenta sobre los SFX, son detalles muy particulares de cada proyecto, por otro lado este mercado está lleno de gente con ganas de trabajar a un precio/beneficio muy bueno, por lo que se decide por contratar diferentes personas para el desarrollo de lo requerido, se gasta menos dinero en cosas que contendrían el assets que no usamos y cumplirian a rajatabla con el diseño. 
 
El mayor mercado dentro de la tienda es en "Scripts", Characters controller, físicas de agua, pathfinding, IA, visual scripts, etc... 
 
 
 
Lo que estoy viendo que realmente falta para UNITY es un buen gestor de interface, es decir un sistema que nos permita gestionar los UI de una manera más profesional, es asqueroso tener que crear mil scripts solo para la interface, es decir, esta termina teniendo más componentes que el juego en sí, luego gestionarlo se hace cada vez más dificil, algo que extraño del MGUI es la libertad de crear múltiples componentes sin lidiar con objetos, etc ... Las instancias, los poolObjects, idearte mil cosas extrañas para que una lista de 1000 objetos no se conviertan en 1000 instancias, etc ... por lo que termina siendo realmente la peor parte de cualquier proyecto.
#362
General (Antiguo) / Resetear posicion waypoint
Enero 08, 2018, 08:26:21 PM
Si lo que quieres hacer es que el auto vuelva a un tiempo atras deberias guardar los datos relevantes en una lista, esto puede ser cada x segundos requiera la interpolación aplicada luego.
 

public class Snapshot
{
public Vector3 Position { get; private set; }
public Quaternion Rotation { get; private set; }
public Snapshot(Vector3 pos, Quaternion rot)
{
   Position = pos;
   Rotation = rot;
}
}
public class SnapshotControl
{
private Queue<Snapshot> _snapshots = new Queue<Snapshot>();
private int _maxSnapshots = 200;
public SnapshotControl(int max)
{
   _maxSnapshots = max;
}
public void Register(Transform t)
{
   _snapshots.Enqueue(new Snapshot(t.position, t.rotation));
   if(_snapshots.Count > _maxSnapshots)
      _snapshots.Dequeue();
}
public Snapshot Get()
{
   if(_snapshots.Count > 0)
      return _snapshots.Dequeue();
   return null;
}
 
public void Clear()
{
   _snapshots.Clear();
}
}

 
De esa manera podrias hacerlo ----
#363
General (Antiguo) / Resetear posicion waypoint
Enero 08, 2018, 11:38:42 AM
A ver, lo tenes que hacer es un arreglo de WayPoints este mismo puede ser de tipo transform, a cada WayPoints le agregas un TAG especial para identificarlos, luego desde una función awake asignas el arreglo.
 
 
 

public class WayPointManager : MonoBehaviour
{
    private GameObject[] _waypoints;
private void Awake()
    {
       _waypoints = GameObject.FindGameObjectsWithTag("WayPoint");
    }
      public Vector3 GetNear(Vector3 from)
      {
         int index = -1;
         float distance = 100000;
         for(int i = 0; i < _waypoints.Length; i++)
         {
            float tmpdistance = (_waypoints.transform - from).magnitude;
            if(tmpdistance < distance)
            {
               index = i;
               distance = tmpdistance;
            }
         }
         return _waypoints[index].transform.position;
      }
}

 
De esa manera podes hacerlo ...
#364
General (Antiguo) / Resetear posicion waypoint
Enero 08, 2018, 01:19:48 AM
Podrias hacer un arreglo con waypoints que recorran todo el circuito y luego lo agregar a un arreglo 
 
por otro lado cuando el coche se da vuelta buscas en el arreglo el waypoints con menor distancia al player.
#365
General (Antiguo) / SCRIPTABLE OBJECTS
Enero 07, 2018, 02:37:21 PM
Lo unico que agregaria al video es que las variables sean privadas y utilizará el atributo SerializeField y luego crearia una propiedad solo GET.
 

public class MiScriptableObject : ScriptableObject
{
        [SerializeField]
        private int _valorA = 0;
        public int ValorA { get { return _valorA; } }
}

 
Esto sirve bastante por que al modificar el valor de un Scriptable Object este no se deshace como lo hacen los objetos MonoBehaviour, no se aplica en todos los casos, pero si en el ejemplo -
#366
Puedes verificar las colisiones de la cámara con un Sphere collider tomar los point para evitar que el jugador traspase las paredes, podrias hacer uso de IK para que se vea bien-
 
Para el problema de la malla de la cabeza, lo que yo hago es poner el Mesh de la cabeza o en su defecto de todo el modelo en un layer donde la camara no la renderize, de esta manera puede localizar la camara mejor -
 
Otra opción es utilizar la ubicación del Hueso de la cabeza y realizar un offset para que esta se mueva junto a la cabeza, pero esto hace que la rotación y los movimientos de la animación afecten la camara, pero con un smoth se puede lograr un buen resultado.
 
Por último, deduzco que el jugador solo se puede inclinar para adelante, por lo que podrias lanzar un RayCast en dirección forward con la distancia mínima permitida según el grado de inclinación y si este colisiona entonces no podrias seguir inclinándose, y no obstante se corregiría tu inclinación segun la información de hit. 
#367
El problema es que Charactercontroller no maneja la gravedad no es un cuerpo con físicas.
 
Para añadir fisica al character controller te recomiendo utilizar un vector donde contengan las velocidades del objeto.
 

private Vector3 _motion;
private void Update()
{
Vector3 axis = //////
if(characterC.isGround)
{
   axis.Normalize();
   _motion = axis;
   _motion *= 10; << o variable de velocidad
   if(Input.GetButton("Jump"))
      _motion.y = 10;
}
_motion.y -= 50 * Time.deltaTime; // Aca le aplicas las fisicas para que el objeto vuelva al suelo --
characterC.Move(_motion * Time.deltaTime);
}

 
Por otro lado, deberias de omitir tener un collider tan grande, deberias de pensar en limitar los movimientos con otra alternativa.
#368
General (Antiguo) / Ayuda con script de inventario
Diciembre 30, 2017, 08:29:17 PM
Si ObjectItem es una estructura opta por cambiarlo a una clase, por otro lado si quieres mantener el tipo podrias hacerlo con default(T) -
 

public struct ItemObject
{
public int ID{ get; set; }
public ...
}
if(item == default(ItemObject)) // Equivalente a NULL -

 
Suerte!
#369
General (Antiguo) / Unet camara independiente por tag
Diciembre 29, 2017, 02:26:56 AM
Cita de: gZone date=1514485897No creo que UNet tenga toda la culpa... el problema es que se confunde en lo más básico, no entiende la lógica.
   
   
       
   
   
       
   
   
      Haz lo que te indica @francoe1...
   
   
      Cliente/servidor y local/no local...
   
   
      Todos los clientes son locales (en su juego) y al mismo tiempo no locales (en el juego del rival).
   
   
      Básicamente se trata de tener una única cámara...
   
   
      ...y cuando tengas al player local en escena haces que la cámara lo siga. No hay más.
   


@gZone No le hecho la culpa a UNET
 
Lo que hace UNET que puede confundir a las personas es una conexión "diferente" por NetworkBehaviour, por ejemplo en los RPC como el siguiente ejemplo 

 
 

[Command]
private void Cmd_move(Vector3 input)
{
 Rpc_move(transform.position);
}
[ClientRPC]
private void Rpc_move(Vector3 pos)
{
 if(!isLocalPlayer)
transform.position = pos;
}

 
Si llamas la función Cmd esta se ejecutara en el servidor y el servidor llamara a Rpc_move en todos los objetos remotos -
 
Internamente el Jugador local envía un paquete etiquetado con su NetworkID + El nombre de la función + Los valores de parámetros serializados mediante Network Writer clase que trabaja junto con un MemoryStream para armar un conjuntos de bytes por último se cierra con un EOF y los bytes son enviados al servidor, el servidor lo recibe y busca el NetworkBehaviour con el ID del paquete, para facilitar estas cosas UNET crea un Diccionario con NetworkID como KEY y NetworkBehaviour como valor, una vez encontrado llama la función, si se hace una llamada de RPC dentro del Comando, UNET envia un paquete similar a a todos los clientes conectados.
 
Entendiendo esto se puede llegar a empezar a armar algo, pero por esta estructura UNET es muy confuso a veces -
 

 Camera.main.GetComponent<CamaraCar1>().SetTarget(GameObject.FindGameObjectWithTag("Player").transform);

 
¿Por qué buscas por TAG?, el problema es que cuando hay más de un jugador el FindGameObjectWithTag seleccionará el primero en la lista, esto es un error de diseño, ¿La variable Player esta asignada? ¿por qué no utilizar esta como target?, por otro lado, CamaraCar1 cuenta con un singleton esto sirve para que no tengas que hacer un GetComponent sobre un objeto que puede ser nulo.
 

public Transform PlayerModel;
public override void OnStartLocalPlayer()
{
CameraCar1.singleton.SetTarget(PlayerModel);
}

 
 
#370
General (Antiguo) / Ayuda con script de inventario
Diciembre 28, 2017, 05:49:38 PM
La mejor opción es la siguiente:
 

public void AddItem(int id, int size)
{
  ItemObject item = _data.Find(x => x.ID == id); // Buscar en el inventario un objeto con el ID
  if(item == null) // Si la busqueda del ITEM no es satifactoria
  {
     item = new ItemObject(id);  // Crear un nuevo item
_data.Add(item); // Agregarlo al inventario
  }
  item.size += size; // Actualizar la cantidad independientemente de si es un nuevo item o si ya existia
}

 
@UnityDevelopersXD El código que estás presentando es un lio, no se necesita un FLAG para saber si se identificó un objeto con el ID indicado, ni siquiera para indicar la creación de un nuevo ítem, por otro lado la función AddItem no tiene que llamar a la función UpdateInventory, si por alguna razón necesitas insertar 100 objetos desde un bucle entonces llamarias 100 veces a la actualización cuando con 1 vez bastaría, el problema se arrastra desde el código original por eso lo comento.
 
 
#371
General (Antiguo) / Unet camara independiente por tag
Diciembre 28, 2017, 05:29:40 PM
Cita de: gZone date=1514475887Confundes la lógica multiplayer...
   
   
      ¿has realizado los tutoriales de UNet?
   
   
       
   


Exactamente! lo que vengo repitiendo a muchos usuarios del foro, UNET no te facilita nada, mas bien te puede llegar hasta complicar las cosas si no entendes como funcionan los socket la serialización, etc ... Todo el apartado de redes es importante -
 
Un juego multijugador no cambia su estructura cuando pasamos de Single a Multi, simplemente cambia el GamePlay - si por ejemplo en tu juego tienes un GameManager con singleton este puede ser usado por el usuario local - pero los usuarios remotos no tienen interacción con los datos locales, es el servidor quien se encarga de todo esto -
 
Para las cámaras, simplemente deja la main camera, y colocas el componente para seguir el target
 

public class CameraCAR : MonoBehaviour
{
public static CameraCAR singleton { get; private set; }
private Transform _target = null;
private void Awake()
    {
   singleton = this;
    }
private void LateUpdate()
    {
   if(_target != null)   
      //Move Cam
    }
public void SetTarget(Transform target)
    {
   _target = target;
    }
}

 
Luego desde el Componente NetworkBehaviour que controla el Cliente seteas el target desde la función virtual OnStartLocalPlayer();
 

public class UNETPlayer : MonoBehaviour
{
public override void OnStartLocalPlayer()
    {
   CameraCAR.SetTarget(Transoform del Objecto del Auto);
    }
}

 
 
#372
General (Antiguo) / CGLocalization
Diciembre 26, 2017, 03:56:46 PM
Como primer consejo, subelo a la tienda de Unity -
 
Excelente herramienta, excelente presentación.
 
Felicitaciones, deberias subirlo a la tienda de Unity - Por último debes presentar el proyecto con algunas imágenes, se ve muy bien -
#373
General (Antiguo) / Creación y destrucción de objetos.
Diciembre 26, 2017, 02:42:34 PM
Cita de: Tizon date=1514293361Hola a todos.
   
   
      Primero feliz navidad y entrada de año a todos.
   
   
      He comprobado que si creas una clase que no herede de nada, puedes ejecutar los constructores. A partir de aquí, mis preguntas. Del mismo modo, si implemento destructores se ejecutarán? Y siguiendo con ello. Hay alguna forma de marcar estos objetos para el borrado? Y siendo así, el destructor cuando se ejecutará? Al marcarlo para el borrado o cuando el sistema efectivamente lo borre? La verdad es que llevo unas cuantas horas buscando información al respecto y me resulta confuso.
   
   
      Muchas gracias a todos.
   


Puedes heredar y aun así utilizar el constructor de la clase, pueden enviar variables a la clase base entre otras cosas, las herencias es algo muy utilizado en la programación orientada a objetos, en el caso de la clase MonoBehaviour no se puede llamar el constructor por la razón que Unity utiliza estas clases tantos para el editor como el runtime, si por ejemplo, queres desde el constructor realizar X tarea como setear valores cada vez que el editor serialize el objeto se perderán posibles configuraciones manuales.
 

public class MiClase : MonoBehaviour
{
public int VariableEditable;
public MiClase()
    {
   VariableEditable = 10;
    }
}

 
En este caso, aunque cambies los valores desde el editor cada vez que se llame a serialización se va a cambiar el valor a diez - para estas tareas esta la función Awake que sirve justamente para suplantar el constructor de las clases MonoBehaviour -
 
Sobre como los objectos se destruyen y como trabaja GC en .NET te dejo este aporte es bastante simple y bueno para entender -
 
https://blogs.msdn.microsoft.com/daniem/2009/07/09/cosas-que-deberas-saber-sobre-el-garbage-collector-de-net/
 
Luego desde Google busca un par de foros sobre como funciona GC en Unity, por que si no mal recuerdo tiene un forma especifica de trabajar para que esto no sea un problema para las diferentes plataformas -
#374
General (Antiguo) / Editor de nivel dentro del juego
Diciembre 26, 2017, 11:39:26 AM
Podrias hacer lo siguiente -
 
Primero necesitas crear una forma de manejar tus prefabs, esta tiene que adaptarse al juego a tu proyecto, en base a esto creas una clase que sirva para componer la información de cada bloque.
 

public class TileBlock
{
public int Prefab { get; private set; }
public GameObject Refecence { get; private set; }
public int PositionX { get; private set; }
public int PositionY { get; private set; }
public int Rotation { get; private set; }
public TileBlock(int prefab, int x, int y)
    {
   Prefab = prefab;
   PositionX = x;
   PositionY = y;
   Reference = MonoBehaviour.Instantiate(Prefab, PositionX, PositionY);
    }
public void Rotate()
    {
   Rotation += 45;
    }
}

 
Anteriormente deberias tener una manera de obtener los prefabs mediante un ID o cualquier identificador, nombre ObjectID, AssetsID, etc.
 
Luego creas un arreglo de TileBlock -
 

public class TileMap
{
private int Width;
private int Height;
public TileBlock[] Tiles { get; private set; }
public TileMap(int width, int height)
{
   Width = width;
   Height = height;
   Tiles = new TileBlock[Width * Height];
}
public void UpdateMap()
    {
   Recorres cada arreglo para instanciar el objecto -
}
}

 
De a poco vas armando la estructura -
 
Por ultimo, lo unico que te interesaria es el Arreglo de TileBlock, puedes utilizar cualquier forma que creas ocurrente para serializar y guardar -
#375
General (Antiguo) / Ayuda con script de inventario
Diciembre 23, 2017, 03:18:39 AM
Cita de: UnityDevelopersXD date=1513984717Hola!
   
   
      Como dice Juanma. 
   
   
      Te explico:
   
   

public void AgrregarItem (int id, int cantidad){
        for (int i = ; i < inventarioo.Count; i++){
            if (inventarioo[i].id == id)
            {
                inventarioo[i] = new ObjetoInvId(inventarioo[i].id, inventarioo[i].cantidad + cantidad);
                ActualizarInventario();
                return;
            }
            inventarioo.Add(new ObjetoInvId(id, cantidad));
            ActualizarInventario();
        }   
}

   
      Allí en ese trozo, si se da cuenta en esta parte: 
   
   

if (inventarioo[i].id == id)
            {
                inventarioo[i] = new ObjetoInvId(inventarioo[i].id, inventarioo[i].cantidad + cantidad);
                ActualizarInventario();
                return;
            }
            inventarioo.Add(new ObjetoInvId(id, cantidad));
            ActualizarInventario();

   
      Estaría diciendo: Si inventario[Numero del contador] tiene un ID que es igual al ID que me han pasado entonces agrega un nuevo objeto al inventario con la cantidad que tenia más la cantidad que me haz pasado, luego actualiza el inventario. (Quita el return, si quieres salir del bucle tienes que colocar break pero no te servirá en este caso).
   
   
      Luego, aún si encontró un ID o no lo encontro, igualmente agregará un nuevo objeto y luego actualiza el inventario.
   
   
      El punto es que estás utilizando el return como para salir del IF y de todo,pero no es así por lo que está siguiendo con el código abajo, para solucionarlo solo debes agregar un else al final de ese IF y meter en sus llaves el código que tienes abajo, quedando así:
   
   

         if (inventarioo[i].id == id)
            {
                inventarioo[i] = new ObjetoInvId(inventarioo[i].id, inventarioo[i].cantidad + cantidad);
                ActualizarInventario();
            }else{
               inventarioo.Add(new ObjetoInvId(id, cantidad));
               ActualizarInventario();
      }

   
      Prueba eso y cuentanos. Creo que debería funcionar porque es lo único que noto.
   
   
      Suerte!!
   


Si hace eso se le agregaria n -x veces objetos al inventario -
 
Una solución más práctica es utilizar un lista y LINQ 

 
 

List<ItemObject> _data = new List<ItemObject>();
public void AddItem(int id, int size)
{
  ItemObject item = _data.Find(x => x.ID == id);
  if(item == null)
     item = new ItemObject(id);  
  item.size += size;
}

 
Pero si aun quiere seguir haciendolo a tu modo entonces separa las funciones de búsqueda -
 

public bool FindObject(int id, out int index)
{
for(; index < inventory.Length; index ++)
   if(inventory[index].ID == id)
      return true;
return false;
}
public void AddItem(int id)
{
int index;
if(FindObject(id, out index))
   inventory[index].cantidad++;
else
   inventory.Add(new ItemObject {ID = id, Cantidad = 1 });
}

 
Pero mientras puedas utilizar LINQ y expresiones lambda se te va a simplificar muchisimo el trabajo -