目录
前言
本文作为学习ml-agents的开篇,主要是参考ml-agents的官方文档,结合Unity和ml-agents创建一个简单的游戏作为强化学习算法的训练环境。本文中用的是官方最新发布的稳定版ml-agents release_1(Version 1.0.0)。整个DIY过程亲测可运行, 并且经过大约半小时的训练小球就足够“智能”,可以很快地找到Target, 最终效果如下:
游戏简介
1. 游戏对象
- Floor:游戏运行的场地, 是一个Plane对象
- Ball:游戏的玩家(Player), 是一个Sphere对象
- Target: 玩家(Player)的目标,是一个Cube对象
2. 游戏逻辑
游戏场景如下:
- 开始:Ball位于Floor中央,Target初始化到Floor上的一个随机位置
- 操作:玩家可以操作Ball在Floor平面上进行滚动。
- 结束:Ball碰到Target or Ball掉落Floor,则该轮游戏结束(即完成一个Episode)。
创建场景
1. 新建对象
在Hierarchy窗口中单击鼠标右键-> 3D Object->分别创建Plane、Sphere和Cube对象。分别在三个对象的Inspector中Reset Transform,如下图
2. 更改属性Transform
- 在Inspector窗口中把Plane的name改为Floor
- 把Sphere的name改为Ball,Position设置为(0,0.5,0)
- 把Cube的name改为Target,Position设置为(2,0.5,4)
3. 添加材质Meterial
- 在Project窗口选中Assets文件夹后单击鼠标右键 -> Create -> Material
- 创建两个Material, 分别命名为Ball Material和Target Material
- Ball Material中的Albedo设置为蓝色,Metallic=0.5,Smoothness=0.8; Target Material中的Albedo设置为黄色,Metallic=0,Smoothness=0.5。设置结果如下:
- 分别把Ball Material和Target Material拖到对应的对象Ball和Target上。
4. 添加组件Component
单击选中Ball->在Inspector窗口的最下面单击Add Component按钮->搜索Rigidbody并添加
PS: 添加Rigidbody使Object具备物理特性,例如重力、作用力等。
5. 整合训练元素
- 新建空Object(Create Empty),重命名为TrainArea, 并Reset。
- 把Floor,Ball,Target拖动到TrainArea中进行分组(这一步操作是为了后面方便创建多个环境并行训练)
创建训练环境
1. 安装ml-agents
- 下载最新发布的稳定版ml-agents到本地:
git clone --branch release_1 https://github.com/Unity-Technologies/ml-agents.git
- 在unity中安装ml-agents包:
在unity->Window菜单->Package Manager->点击"+", Add package from disk…->定位到下载的ml-agents/com.unity.ml-agents目录,选择package.json打开。安装完成后在Project窗口的Packages目录下出现ML Agents包
- 通过PyPi安装Python包mlagents:
pip3 install mlagents
运行完成后可以通过运行"mlagents-learn --help"命令验证是否成功安装。
2. 游戏初始化
- 在Ball上增加script
单击选中Ball->在Inspector窗口的最下面单击Add Component按钮->搜索script, 选择New script, 命名为"BallAgent"-> 点击Create and Add按钮
创建完成后可以在Project窗口的Assets目录下找到新建的BallAgent脚本
- 导入需要的包
双击BallAgent脚本, 在编辑器中打开, 在首行添加
using Unity.MLAgents;
using Unity.MLAgents.Sensors;
把基类MonoBehaviour改为Agent。删除Update()方法,保留Start()方法。更新后结果如下:
- 编写初始化方法
初始化方法主要是两个:Start(), OnEpisodeBegin()
- Start: 在整个程序运行前被调用,用来初始化整个游戏程序
- OnEpisodeBegin: 在一轮游戏运行时被调用,用来初始化本轮的游戏场景
初始化代码如下:
using System.Collections.Generic;
using UnityEng