MLAgents (1) 球移动到指定立方体目标

1、ML-Agents库介绍

ML-Agents库,训练用于2D、3D、VR/AR游戏的智能agent,经过训练的agent可用于多种目的,包括:控制NPC行为(采用各种设置,例如多个agent和对抗)、对游戏内部版本进行自动化测试、以及评估不同游戏设计决策的预发布版本

2、Unity中创建立方体、球和地面

球——玩家移动和AI控制

立方体——需要球移动到的位置,当移动到距离达到指定阈值时为移动成功

成功目标:将球移动到立方体位置

失败条件:球出界(落出地面)

3、创建脚本

创建RollerAgent脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 导入ML-Agents库
using Unity.MLAgents;
using Unity.MLAgents.Sensors;
using Unity.MLAgents.Actuators;

public class RollerAgent : Agent
{
    // 要移动到目标立方体的位置
    public Transform target;
    // 刚体力的倍数
    public float forceMultiplier = 10.0f;
    private Rigidbody rigidbody;

    // Start is called before the first frame update
    void Start()
    {
        rigidbody = this.GetComponent();
    }

    // 每次训练开始时调用,可以用来初始化 AI和环境
    // 调用场景中每个Agent,开始函数
    public override void OnEpisodeBegin()
    {
        //base.OnEpisodeBegin();
        // 当球出界,重置球的位置到原点
        if(this.transform.localPosition.y  < 0.5)
        {
            this.rigidbody.velocity = Vector3.zero;
            this.rigidbody.angularVelocity = Vector3.zero;
            this.transform.localPosition = new Vector3(0.0f, 0.5f, 0.0f);
        }

        // 目标立方体随机出现在场地某个位置
        target.localPosition = new Vector3(Random.value * 8 - 4, 0.5f, Random.value * 8 - 4);  // [-4, 4 之间随机生成立方体]  Random.value值为[0~1]
    }

    // 每走一步收集AI所需要的矢量信息,AI通过这些信息了解现在的环境
    // sensor.AddObservation() 方法收集所需数据
    // 通过调用场景中每个Agent的CollectObservations(VectorSensor sensor)函数,收集有关场景的信息,更新他们的Sensor并收集 观测向量
    public override void CollectObservations(VectorSensor sensor)
    {
        //base.CollectObservations(sensor);

        // sensor.AddObservation() 方法收集所需数据
        // 收集目标正方体 和 球的位置
        sensor.AddObservation(target.localPosition);
        sensor.AddObservation(this.transform.localPosition);

        // 收集球的速度
        sensor.AddObservation(this.rigidbody.velocity.x);
        sensor.AddObservation(this.rigidbody.velocity.z);
    }

    /// 
    /// 指定每一步的AI的行为
    /// ML-Agents支持两种类型的操作:连续和离散。通过actions.ContinuousActions数组来记录所有连续的操作
    /// 需要在BehaviorParameters组件中设置连续型操作个数和离散型操作个数,以及每个离散型操作的可能数
    /// 在ppo算法中数组内的每一个值都在[-1, 1]之间
    /// 
    /// actions.DiscreteActions数组记录所有离散 的操作,每个值时0~x中的整数,x表示该操作的所有可能性的总数(例如 :实现跳跃 0代表不跳 ,1代表跳)
    /// 调用每个Agent的OnActionReceived()函数,传递Agent根据策略选择的动作
    /// 
    /// 
    public override void OnActionReceived(ActionBuffers actions)
    {
        //base.OnActionReceived(actions);

        Vector3 controlSignal = Vector3.zero;
        controlSignal.x = actions.ContinuousActions[0];
        controlSignal.z = actions.ContinuousActions[1];
        // 将当前动作赋值给球
        this.rigidbody.AddForce(controlSignal * forceMultiplier);

        // rewards
        // 判断球和目标立方体之间 的距离
        float distanceToTarget = Vector3.Distance(this.transform.localPosition, target.localPosition);
        // 如果距离靠近
        if (distanceToTarget < 1.42f) 
        {
            // SetReward() 本次决策的奖励值设为多少  AddReward() 本次决策的奖励值加多少
            this.SetReward(1.0f);
            // 结束本次训练,进入初始化状态再次进行训练
            this.EndEpisode();
        }

        // 当掉出场地时,结束本次训练,进入初始化状态再次进行训练
        if(this.transform.localPosition.y < 0)
        {
            // 用EndEpisode()结束这次训练,然后进入初始化状态再次进行训练
            // 已经到达设定的Max Step或Agent将自身标记为EndEpisode(),调用 Agent的OnEpisodeBegin()函数,结束
            this.EndEpisode();
        }
    }
    
    // 启发函数,增加手动测试功能,实现玩家可以通过自己的输入控制AI,方便排查环境中是否有bug,是否可以正常运行
    public override void Heuristic(in ActionBuffers actionsOut)
    {
        //base.Heuristic(actionsOut);
        // 人工操作
        ActionSegment continuousActionsOut = actionsOut.ContinuousActions;
        // 按 a/d 左右 w/s 上下
        continuousActionsOut[0] = Input.GetAxis("Horizontal");
        continuousActionsOut[1] = Input.GetAxis("Vertical");
    }
}

将脚本加入到球体上,此时球体会增加脚本

Behavior Parameters(行为参数)——每个代理必须有一个行为。行为决定了代理如何做出决策

Decision Requester——用于AI从模型申请动作。设置决策间隔太短的话会占很多计算资源,在不影响AI效果的情况下越大越好。

4、对整体流程的总结

OnEpisodeBegin——训练初始化AI和环境,训练开始时调用

CollectObservations——收集每一步AI的矢量信息

        使用 sensor.AddObservation,收集所需数据

OnActionReceived——行为有连续和离散之分,将行为赋值给AI,并判断结束本次训练的条件,

        设置奖励值SetReward()

EndEpisode——结束本次训练,进入初始化后再次进行训练

Heuristic——实现玩家通过自己的输入控制AI,方便排查环境是否有bug

你可能感兴趣的:(unity,机器学习)