実行したいこと
現在、Unityで,マップ内の建物をよけながら車を運転するBotをML-Agentsで実装しているのですが、自分が作ったBotの車がうまく進んでもらえず、ずっとその場でくるくる回っているだけです。
報酬内容
- 前進、後退をするごとに報酬(0.001)を与える
- くるくる回るのを防ぐため、 ハンドルを動かすと罰(-0.001)を与える
- スポーンから300秒すると強制的にリスポーン
- 死亡または壁にぶつかると罰(-10)を与える
毎回100万回ほど学習させていました。
コード
C#(Bot_ML.cs)
1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using Unity.MLAgents; 5using Unity.MLAgents.Sensors; 6using Unity.MLAgents.Actuators; 7 8public class Bot_ML : Agent //Agentクラスを継承する 9{ 10 public Bot bot_script; 11 public BotCar botcar_script; 12 13 public GameObject guns; 14 15 private void Awake() 16 { 17 18 } 19 20 //インスタンス生成時に呼ばれるメソッド 21 public override void Initialize() 22 { 23 24 } 25 26 public override void OnEpisodeBegin() { 27 28 } 29 30 31 // 観察の収集 32 public override void CollectObservations(VectorSensor sensor) { 33 } 34 public override void OnActionReceived(ActionBuffers vectorAction){ 35 36 //操縦 37 int move_action = (int)vectorAction.ContinuousActions[0]; 38 39 if(move_action == 1){ //前進 40 botcar_script.moveint = 1; 41 AddReward(0.001f); 42 } 43 if(move_action == 2){ //後退 44 botcar_script.moveint = 2; 45 //AddReward(0.001f); 46 } 47 48 int turn_action = (int)vectorAction.ContinuousActions[1]; 49 50 if(turn_action == 1){ 51 botcar_script.turn_int = 1; //左折 52 AddReward(-0.001f); 53 } 54 if(turn_action == 2){ 55 botcar_script.turn_int = 2; //右折 56 AddReward(-0.001f); 57 } 58 } 59 60 public void dead(){ 61 AddReward(-10f); 62 //エピソード終了 63 EndEpisode(); 64 return; 65 } 66 67}
C#(BotCar.cs)
1using UnityEngine; 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine.UI; 5using Random = UnityEngine.Random; 6 7[System.Serializable] 8public class AxleInfo { 9 public WheelCollider leftWheel; 10 public WheelCollider rightWheel; 11 public bool motor; 12 public bool steering; 13} 14 15public class BotCar : MonoBehaviour { 16 public List<AxleInfo> axleInfos; 17 public float maxMotorTorque; 18 public float maxSteeringAngle; 19 private float NomalMotorTorque; 20 private float ADSMotorTorque; 21 private float BoostMotorTorque; 22 public sys sys_script; 23 //===settings=========================// 24 public int moveint = 1; 25 public int turn_int = 0; 26 //=================================// 27 //Bot_ML 28 public Bot_ML ml_script; 29 30 void Start() 31 { 32 NomalMotorTorque = maxMotorTorque; 33 } 34 // 対応する視覚的なホイールを見つけます 35 // Transform を正しく適用します 36 public void ApplyLocalPositionToVisuals(WheelCollider collider){ 37 if (collider.transform.childCount == 0) { 38 return; 39 } 40 41 Transform visualWheel = collider.transform.GetChild(0); 42 43 Vector3 position; 44 Quaternion rotation; 45 collider.GetWorldPose(out position, out rotation); 46 47 visualWheel.transform.position = position; 48 visualWheel.transform.rotation = rotation; 49 } 50 51 private float motor; 52 private float steering; 53 public void FixedUpdate(){ 54 foreach (AxleInfo axleInfo in axleInfos) { 55 if (axleInfo.steering) { 56 axleInfo.leftWheel.steerAngle = steering; 57 axleInfo.rightWheel.steerAngle = steering; 58 } 59 if (axleInfo.motor) { 60 axleInfo.leftWheel.motorTorque = motor; 61 axleInfo.rightWheel.motorTorque = motor; 62 } 63 ApplyLocalPositionToVisuals(axleInfo.leftWheel); 64 ApplyLocalPositionToVisuals(axleInfo.rightWheel); 65 } 66 } 67 void Update(){ 68 switch(moveint){ //移動 69 case 1: //前進 70 motor += maxMotorTorque * Time.deltaTime; 71 //StartCoroutine("RandomMoveint"); 72 break; 73 case 2: //後退 74 motor -= maxMotorTorque * Time.deltaTime; 75 //StartCoroutine("RandomMoveint"); 76 break; 77 } 78 switch(turn_int){ 79 case 1: //左折 80 if(steering <= -maxSteeringAngle){ 81 steering -= maxSteeringAngle * Time.deltaTime; 82 //StartCoroutine("RandomMoveint"); 83 } 84 if(steering <= maxSteeringAngle){ 85 steering = -maxSteeringAngle; 86 } 87 break; 88 case 2: //右折 89 if(steering <= maxSteeringAngle){ 90 steering += maxSteeringAngle * Time.deltaTime; 91 //StartCoroutine("RandomMoveint"); 92 } 93 if(steering <= maxSteeringAngle){ 94 steering = maxSteeringAngle; 95 } 96 break; 97 } 98 } 99}
C#(Bot.cs(一部のみ抜粋))
1private IEnumerator autoRespawn(){ 2 yield return new WaitForSeconds(300f); 3 StartCoroutine("dead"); //死亡処理 4} 5public void atDead(){ 6 StartCoroutine("dead"); //死亡処理 7}
試したこと
こちらのサイトを参考にして上記の報酬を設定したのですが、うまく動作しませんでした。
説明の不足などがあれば追記します。

あなたの回答
tips
プレビュー