C++: Cargar y ejecutar Python (Scripting)

C++ es un lenguaje de programación muy poderoso, pero uno de sus ventajas es que una vez compilado, si necesitas hacer ciertos cambios se requiere de utilizar el código fuente,  por lo que si necesitamos que un usuario pueda hacer ciertos cambios sin darle el código fuente, podemos darle la oportunidad de generar scripting, en este articulo mencionare como cargar y ejecutar código de Python desde C++ y la comunicación en ambos sentidos. En videojuegos es una manera tradicional de permitir al usuario genere sus propios mods, entre otros usos.

Configuración básica:

  • Instalar Python (En este ejemplo yo utilize 3.6) de preferencia en «C:/Python36».
  • Crear un proyecto de consola en C++.
  • Compilar el «hola mundo» para que genera la carpeta de .exe.
  • Copiar «python36_d.dll» donde esta el .exe.
  • Agregar al proyecto include de «C:\Python36\include» y Lib a  «C:\Python36\Lib».

Leer más

IA básico de un vehículo

En este articulo hablare un poco de como crear una inteligencia artificial para un vehículo para que pueda recorrer por si mismo, para este ejemplo me base en el proyecto de como crear una nave al estilo hoverboard en Unity. Es una demostración sencilla de como puede crearse uno, puede mejorarse, pero la intención era hacerlo lo más sencillo y funcional.

La inteligencia artificial de este ejemplo lleva acabo 3 tareas: primero si debe acelerar o frenar, si debe ir girando a la derecha o izquierda y esta frente a una pared, determinar en que sentido es más posible poder continuar su camino.

1°- Determinar si debe acelerar o frenar: Para esto simplemente se lanza un raycast hacía adelante del vehículo a 7 unidades de Unity, si este no impacta en nada entonces aceleramos, si impacta con algo dejamos de avanzar (la nave estilo hoverboard cuenta con inercia), esto para dejar que pueda llevar acabo mejor una vuelta.

2°- Determinar para donde debe girar: En este proceso se lanza 2 raycast hacía adelante pero en diagonal igual de 7 unidades, entonces en el caso del lado derecho, si este impacta, entonces indicamos que debe girar hacía la izquierda (para alejarnos de la pared) y sin importar si impacto o no, se hace lo mismo hacia el lado izquierdo, done si impacta con lago giramos hacía la derecha, ocasionando que en el caso que ambos hayan indicado que deben girar se anulen y simplemente siga hacía el adelante el vehículo.

3°- Estar frente a un pared, determinar si a la derecha o izquierda es más posible continuar con el camino: Existe un caso especial que puede ser que el paso 1 y 2 no fueron suficiente y termine el vehículo a frente de una pared y se debe determinar hacía donde es más posible continuar con nuestro camino, es aquí que se lanza un raycast totalmente hacía la derecha y otro hacía la izquierda, y si uno de estos raycast no impacto en nada, entonces le indicamos al vehículo  que gire hacía esa dirección hasta que el paso 1 y 2 vuelvan a permitir que pueda continuar con su camino.

En el gif solo se ven por muy pocos frames.

Aquí les dejo el enlace para descargar el proyecto completo: DESCARGAR

Notas para atender mejor el ejemplo:

  • transform.TransformDirection(Vector3.forward) : Para poder lanzar un raycast hacía adelante del vehículo uso la función TransformDirection de transform que me convierte el Vector3.forward en otro vector3 pero con lo que representa hacía adelante del vehículo, y así para todos los sentidos.
  • LayerMask: Este tipo de variable ayuda hacer que el raycast ignore el mismo vehículo (esto para poner muchos vehículos 😉  ).
  • horizontal = (AfrenteDer == false) ? 0f : -1.0f;   Este es una manera de implicar un if, donde si la variable ‘AfrenteDer’ es igual a falso, entonces ‘horizontal’ es igual a 0.0f, en caso contrario (else), ‘horizontal’ va ser igual a -1.0f.

Unity – Detectar mientras se deja presionado botón en UI

El sistema de UI de Unity cuenta con botones pero tienen el pequeño problema que solo activan el evento de presionado y no mientras se mantenga presionado, por eso les comparto aquí un pequeño script que solo deben agregar a su proyecto y con esto agregar a cualquier botón que necesiten que llame una función mientras se encuentre presionado y agregar en su eventos que función llamara como ya funciona el sistema de eventos de Unity.

 

Como funciona:

Unity aparte de agregar eventos desde el inspector puedes recibirlos directamente por script usando el EventSystem y así poder detectar cuando es presionado y cuando se deja de presionar, y mientras se encuentre presionado, se llama la función que ah sido agregado como a una variable del tipo UnityEvent.

Guardar todos los sprites de un atlas como png independientes (Solo Editor)

Este script permite convertir todos los sprites de un atlas o textura que hayan sido recortado con la herramienta de Unity en imágenes independientes png y almacenarlas en el disco duro, y poder usarlo fuera de Unity (Que fue el motivo real por el que lo cree).

Campus Party México 2017 Workshop Pacman

Aquí les dejo el proyecto completo hasta donde se llego en el workshop que impartí en el campus party méxico 2017.

La carpeta comprimida también incluye la diapositiva que se presento.

Proyecto Pacman

PARCHE: Hay un pequeño problema con los fantasmas que cuando tiene que usar los nodos del centro que teletransportan de un lado a otro, estos solo atraviesan todo el nivel, por lo que este código al inicio de «ActualizarLerp» en los fantasmas podría solucionarlo (Lo hice al aire, si alguien lo prueba y verifica se agradecería)

//Son casos especiales en nodos especiales que teletransprotan al fantasma 
if (Camino[IndexInResult] == new Vector3(35f, 0f, -2.3f)) //Es nodo de hasta la derecha especial?
 {
      transform.position = Camino[IndexInResult]; // 3 Es es nodo derecho
      IndexInResult++;
 }
 else if(Camino[IndexInResult] == new Vector3(-35f, 0f, -2.3f)) //Es el nodo de la izquierda
 {
       transform.position = Camino[IndexInResult]; //2 es nodo izquierdo
       IndexInResult++;
 }

 

Unity- Manejar los Tag y los Layers de manera facil en scripts

Los Tag y los Layers son muy usados en Unity, pero también muy factibles a que nos generen problemas. De manera básica los Tags permite comparar GameObject por tag para si tienes muchos tipos de enemigo, pero solo quieres saber si es enemigo y no de su tipo, solo puedo preguntar por su tag (Uso común en los Collision y Trigger) y los Layers funcionan para indicarle a la camara que GameObjects puede ver y cuales no, en las luces sobre que GameObject puede iluminar y cuales no y por ultimo en las físicas para hacer que por ejemplo las balas no puedan colisionar entre ellos (Matrix de colisión) o que un Raycast ignore ciertos objetos, entre sus principales usos.

Ambos presentan algunos problemas al trabajar con ellos dentro de un script:

  1. En caso de Tag podemos escribir «player» y este no va funcionar porque es con ‘P’ mayúscula y esto no hay manera hasta el ya probar si estamos en lo correcto o no.
  2. Si en un script comparamos con el Tag de «Pared» y pasa el tiempo y según nosotros no se utiliza y lo eliminamos de la lista de Tags, Unity no te notificara si hay un script que lo este utilizando o no, solo dejaran de hacer lo que esperamos estos scritps, en pocas palabras no sabemos si se utiliza o no en scripts un Tag.
  3. En Layers las operaciones o suelen ser ‘ 1 << NumeroLayer ‘  o ‘ 1 << LayerMask.NameToLayer («MiLayer») ‘ donde o no sabemos bien que numero es cada layer o en el caso dos, el mismo problema con los Tags no sabemos si esta bien escrito o en caso de eliminarlo no saber de manera inmediata si lo esta utilizando o no un script.

Una solución aparte de ser cuidadoso, es crear un script que tenga puras constantes con los nombres de los Tags y Layers para tenerlos en un lugar y actualizarlos de manera manual cualquier cambio. Entonces se puede generar un script que genere este script de manera automática con el fin que sea más rápido y estar 100% que se escribe de manera correcta.

Al final pongo el código del script que solo debes agregar a tu proyecto y debe estar dentro de una carpeta llamada ‘Editor’ y en ‘Edit / Generate Constants Classes’  y se auto generan los scripts. Con esto ya en cualquier script en vez de compara el Tag de «Player», solo debes usar ‘ k.Tags.PLAYER’ el cual es un string constante, esto asegura que el string esta correctamente escrito y si se llegara eliminar el Tag al actualizar los archivos,  como los scripts hacen referencia a una variable, marcaría un error en todos los scripts que necesitan ese Tag y se aplica lo mismo con los Layers. De esta manera resolvemos los problemas mencionados anteriormente.

 

 

Seguridad: Ataques de unicode, IDN, phishing o páginas falsas

Últimamente a empezado a crecer considerablemente los fraudes y infecciones de malware por páginas falsas (También conocido como ataques unicode, ataques de IDN o phising) por lo que en este articulo explicare de manera muy general y sencillo que son y como protegernos de este tipo de páginas.

¿Que es?

Este tipo de engaños consiste en usar letras básicamente iguales (pero para las máquinas no lo son) para tener una página web que su nombre puede parecer bastante similar a otra por ejemplo ‘wһатѕарр.com’ no es ‘whatsapp.com’ (Observa bien la primera ‘T’).  Cuando uno registra una página web se debe registrar con un nombre y este es único a nivel mundial, pero por motivos que existen varios idiomas en el planeta, una letra como en este caso la T para otras escrituras la letra T o inclusive una similar se es procesada como otra letra y esto permite generar registrar páginas web con nombres muy similares pero no lo son, otro ejemplo por ejemplo puede ser con ‘google’ donde se podría registrar una página que en vez de 0, fuera el numero cero (0) entonces tendría la página web ‘g00gle.com’ que un usuario no ingresaría esta página directamente, pero si podría mandar un correo electrónico o publicidad que indicara algo como visita ‘g00gle.com’ y al entrar infectar la máquina del visitante con un virus.

Existen muchas letras que se pueden usar para registrar páginas muy parecidas a populares y existen casos donde el navegador web puede interpretar una letra y mostrarla como si fuera otra como puede ser el caso de ‘https://www.аррӏе.com‘ que realmente es ‘https://www.xn--80ak6aa92e.com/’ pero el navegador lo mostrara como ‘apple’ aunque no lo sea, estos casos son más difíciles de distinguir.

¿Como protegernos?

Lo mejor es tener actualizado nuestros navegadores siempre a la ultima versión, donde por ejemplo la version 58 de Chrome arregla el problema de ‘apple.com’ donde ya muestra el texto original, pero en caso de firefox se tiene que activar de manera manual esto, donde tenemos que escribir como página ‘about:config‘ y en buscar ‘ponycode’ y la opción de ‘network.IDN_show_punycode’ debe estar activo en true, si se encuentra en falso, solo debemos dar doble clic.
Fuera de esto lo aconsejable es siempre observar a que enlaces nos quiere llevar links que recibimos y si se ve raro, no confiar en el sitio web, igual en todo caso puedes buscar el sitio web desde un buscador, estos siempre omiten este tipo de páginas por motivos obvios de seguridad.

Unity- Hacer que el ParticleSystem ignore la pausa o el timeScale

¿Como hacer que las partículas funcionen en pausa? o ¿Como hacer que un el particlesystem ignore la escala de tiempo? Este es una pregunta un poco recurrente entre mis alumnos y en algunos foros y la respuesta es bastante sencilla.

El Time.timeScale se encarga de manejar a la velocidad que se actualiza el mundo y por defecto es un valor de 1, si este se vuelve 0, las animaciones, físicas y partículas se congelan porque dependen de este. Pero existe una manera de que las partículas puedan ignorar la escala de tiempo y es simplemente forzar su actualización con un script que tenga el siguiente codigo:


//Referencia a las particulas
ParticleSystem parti;

private void Awake()
{
parti = GetComponent<ParticleSystem>();
}

void Update()
{
parti.Simulate(Time.unscaledDeltaTime, true, false);
}

Y poner el script en las partículas, este avanza porque usamos el unscaledDeltaTime que como su nombre lo indica no le afecta la escala de tiempo y usamos la función de las partículas que los sigue reproduciendo.

Unity – Nave al estilo hoverboard

Me encontré con este interesante tweet de KevKev https://twitter.com/Der_Kevin/status/846690600942489602

Así que hice una versión exageradamente sencilla de una nave (que es un cubo, pero imagen que es una nave bien bonita con partículas y todo) que flota al estilo hoverboard pero control estilo de vehículo volador. Aquí dejo un gif y el proyecto completo elaborado en Unity 5.6

Demo

Proyecto

Unity – Posicionamiento de pies a suelo con IK

Los IK de Unity es una herramienta que permite poder controlar a donde mira la cabeza o posicionar los pies o las manos a una posición o rotación y se mezcla con las animaciones, no explicare usar los IK pero aquí dejo la documentación oficial.

Demo

Se pueden utilizar los IK para posicionar el pie a la altura de la plataforma donde está tocando y también que tome la rotación de la plataforma. Entonces la lógica consiste en lanzar un RayCast desde la posición del pie hacia abajo y en donde impacte el Raycast, y posicionar el pie con IK en donde impacto el Raycast, esto es la teoría básicamente.

Ahora puntos importantes a considerar:

  • Al posicionar el pie en donde impacto el Raycast el pie estará dentro del suelo un poco porque los huesos del pie no están exactamente en la planta del pie (Imagínate si es una mujer con tacones), entonces tienes que sumarle un offset para compensar esta parte.
  • El Raycast tiene que ser lanzado desde donde se encuentra el pie y un poco más arriba. Esto se puede solucionar usando ‘GetIKPosition(AvatarIKGoal.RightFoot);’ del animator.
  • El Raycast es recomendable usar con LayerMask para evitar que termine colisionando con el mismo personaje.
  • Si el Raycast no impacto con nada, no asignamos una posición (Se deja según la animación indique).

Mi proyecto consiste en un script que solo es necesario poner en un personaje junto el Animator para que empiece a funcionar y una pequeña escena (el gif) para verlo en acción.

El proyecto lo tengo en GitHub: IKFoot_Floor-Unity