1, ml agent和 tensorflow的关系
mlagent 是unity专用ai组件,依赖tenslorflow (python环境)和 tensorflowsharp(unity插件,使unity程序可以包含一个tensorflow内核。该内核可跨平台,但不支持keras api。git 上又一个keras sharp的组件30+星,但问题很多)
https://blog.csdn.net/linxinfa/article/details/79712513
https://www.jianshu.com/p/31844f586b04
https://blog.csdn.net/lengyoumo/article/details/90485127
https://blog.csdn.net/u010019717/article/details/80382933
这是一片不错的教程
加入ML-Agent打包后,build出c端程序,可以使用专用训练指令,借c端程序训练模型。训练出的模型扩展名为.nn, 正常启动游戏并指定.nn模型,即可借由内部的tensorflowsharp 运行。
如果使用mlagent处理ai,那么程序打包出来后,你无法再对训练脚本进行修改。如果你希望可以使用python即时调整训练元素,或是即时使用模型影响游戏,那么使用socket之类的通信方法就可以解决这个问题。实际上,如果程序有“用户训练”的需求,那么最好使用这种方式。如果没有。那么直接使用mlaget 训练得到模型后再打包,是最好的方法。
ML-Agent 有自己的api。在程序中,设定关注的参数并设置奖励,即可使用。不像tensorflow,还需要构建训练过程。
如果要使用tensorflow的api功能,直接调用tensorflow sharp 即可。 但,不支持keras api ! 也不支持keras 模型格式。
在我的另一篇教程里有详细的安装教程
https://mp.csdn.net/mdeditor/90413429#
这个哥们写的概念介绍文章狠不错
https://blog.csdn.net/u010019717/article/details/80382933
首先为目标物体添加agent(Agent组件用于收集 目标信息,或驱动目标)
创建一个脚本,继承agent 并重写agent的生命周期方法。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MLAgents;
public class Ball3DAgent : Agent
{
[Header("Specific to Ball3D")]
public GameObject ball;
private Rigidbody ballRb;
//目标是一个叫ball的gameobject,该ball 有Rigidbody组件。在agent初始化的时候我们需要获取这些对象。
//周期:初始化agent
public override void InitializeAgent()
{
ballRb = ball.GetComponent<Rigidbody>();
}
//周期:收集信息
public override void CollectObservations()
{
//增加收集数据,gameobject指的是球下面的平板,此处收集平板的旋转x,z以及目标球与木板的位置差,和目标球的速度。
AddVectorObs(gameObject.transform.rotation.z);
AddVectorObs(gameObject.transform.rotation.x);
AddVectorObs(ball.transform.position - gameObject.transform.position);
AddVectorObs(ballRb.velocity);
}
//周期:agent驱动,每帧都会运行,一个breain可以对应多个agent,但一个agent只能对应一个breain
//该周期接收来自breain的驱动指令,获得float数组和string数据.其中数组数据根据CollectObservations周期中的数据顺序排序。
public override void AgentAction(float[] vectorAction, string textAction)
{
if (brain.brainParameters.vectorActionSpaceType == SpaceType.continuous)
{
var actionZ = 2f * Mathf.Clamp(vectorAction[0], -1f, 1f);
var actionX = 2f * Mathf.Clamp(vectorAction[1], -1f, 1f);
if ((gameObject.transform.rotation.z < 0.25f && actionZ > 0f) ||
(gameObject.transform.rotation.z > -0.25f && actionZ < 0f))
{
gameObject.transform.Rotate(new Vector3(0, 0, 1), actionZ);
}
if ((gameObject.transform.rotation.x < 0.25f && actionX > 0f) ||
(gameObject.transform.rotation.x > -0.25f && actionX < 0f))
{
gameObject.transform.Rotate(new Vector3(1, 0, 0), actionX);
}
}
if ((ball.transform.position.y - gameObject.transform.position.y) < -2f ||
Mathf.Abs(ball.transform.position.x - gameObject.transform.position.x) > 3f ||
Mathf.Abs(ball.transform.position.z - gameObject.transform.position.z) > 3f)
{
Done();
//设置奖励 -1
SetReward(-1f);
}
else
{
//设置奖励+0.1
SetReward(0.1f);
}
}
//重置代理 (新一轮训练,各个物体的初始状态)
public override void AgentReset()
{
//平面角度
gameObject.transform.rotation = new Quaternion(0f, 0f, 0f, 0f);
gameObject.transform.Rotate(new Vector3(1, 0, 0), Random.Range(-10f, 10f));
gameObject.transform.Rotate(new Vector3(0, 0, 1), Random.Range(-10f, 10f));
//初始化球
ballRb.velocity = new Vector3(0f, 0f, 0f);
ball.transform.position = new Vector3(Random.Range(-1.5f, 1.5f), 4f, Random.Range(-1.5f, 1.5f)) + gameObject.transform.position;
}
}