Curso de Inteligencia Artificial con ML-Agents de UNITY. Introducción.
Creamos un minijuego y nos enfrentamos al MLAgent
Cualquier duda o comentario de la lección podéis dejarla en el foro del curso.
Utilizamos lo aprendido para crear un minijuego. Usamos uno de los ficheros creados en el proceso de aprendizaje para darle la inteligencia al agente. Así podemos distribuir el juego y tener a nuestros agentes funcionando sin necesitar un entorno de conda diciéndole que tiene que hacer.
Script del agente con las modificaciones:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using Unity.MLAgents; using Unity.MLAgents.Sensors; public class HumanoidML : Agent { [Header("Velocidad")] [Range(0f, 5f)] public float _speed; [Header("Velocidad de giro")] [Range(50f, 300f)] public float _turnSpeed; public bool _training = true; private Rigidbody _rb; [SerializeField] private Transform _target; private Animator _anim; private Vector3 _previous; public Text _contadorText = null; public float _puntos = 0; public override void Initialize() { _rb = GetComponent<Rigidbody>(); _anim = GetComponent<Animator>(); _previous = transform.position; //MaxStep forma parte de la clase Agent if (!_training) MaxStep = 0; } public override void OnEpisodeBegin() { _rb.velocity = Vector3.zero; _rb.angularVelocity = Vector3.zero; MoverPosicionInicial(); _previous = transform.position; } public override void OnActionReceived(float[] vectorAction) { float lForward = vectorAction[0]; float lTurn = 0; if (vectorAction[1] == 1) { lTurn = -1; } else if (vectorAction[1] == 2) { lTurn = 1; } _rb.MovePosition(transform.position + transform.forward * lForward * _speed * Time.deltaTime); transform.Rotate(transform.up * lTurn * _turnSpeed * Time.deltaTime); } public void Update() { float velocity = ((transform.position - _previous).magnitude) / Time.deltaTime; _previous = transform.position; _anim.SetFloat("multiplicador", velocity); } public override void Heuristic(float[] actionsOut) { float lForward = 0f; float lTurn = 0f; if (Input.GetKey(KeyCode.UpArrow)) { lForward = 1f; } if (Input.GetKey(KeyCode.LeftArrow)) { lTurn = 1f; } else if (Input.GetKey(KeyCode.RightArrow)) { lTurn = 2f; } // Put the actions into an array and return actionsOut[0] = lForward; actionsOut[1] = lTurn; } public override void CollectObservations(VectorSensor sensor) { //Distancia al target. //Float de 1 posicion. sensor.AddObservation( Vector3.Distance(_target.transform.position, transform.position)); //Dirección al target. //Vector 3 posiciones. sensor.AddObservation( (_target.transform.position - transform.position).normalized); //Vector del señor, donde mira. //Vector de 3 posiciones. sensor.AddObservation( transform.forward); } private void OnTriggerStay(Collider other) { if (true) { if (other.CompareTag("target")) { DaPremio(0.5f); } if (other.CompareTag("borders")) { DaPremio(-0.05f); } } } private void DaPremio(float premio) { AddReward(premio); if (_contadorText != null) { _puntos += premio; _contadorText.text = _puntos.ToString(); } } private void MoverPosicionInicial() { bool posicionEncontrada = false; int intentos = 100; Vector3 posicionPotencial = Vector3.zero; while (!posicionEncontrada || intentos >= 0) { intentos--; posicionPotencial = new Vector3( transform.parent.position.x + UnityEngine.Random.Range(-3f, 3f), 0.555f, transform.parent.position.z + UnityEngine.Random.Range(-3f, 3f)); //en el caso de que tengamos mas cosas en el escenario checker que no choca Collider[] colliders = Physics.OverlapSphere(posicionPotencial, 0.5f); if (colliders.Length == 0) { transform.position = posicionPotencial; posicionEncontrada = true; } } } }
Como veis las posibilidades de creación de enemigos son muy grandes. Podemos usar diferentes ficheros de configuración, con diferentes niveles de inteligencia, o entrenados para tener en cuenta unas variables diferentes para crear agentes con diferente personalidad.
Hemos visto lo básico más básico de los MLAgents, pero lo hemos visto en muy poco tiempo y hemos aprendido muchisimo. Tenemos una buena base para pensar nuevos desafíos, nuevos personajes, nuevos comportamientos…. pero nos falta ver mucho sobre los MLAgents.
Es un mundo nuevo, que ya lleva años de investigación, pero que esta empezando ahora a ser usable. Espero poder profundizar más en próximos cursos, explicar las variables de configuración, como afectan, y sobretodo crear comportamientos más complejos que nos planteen retos nuevos.