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; } }