---
# System prepended metadata

title: Unity ML-Agents
tags: [Unity, 強化学習]

---

Unity ML-Agents
===
###### tags: `Unity` `強化学習`

機械学習において、Unityを使って環境構築する。

用意するもの
---

#### Unity Environment
Unityで環境を生成する。環境で使用するオブジェクトにはmlagentsが用意したファイルを利用する。

#### Python API (Jupyter Notebook (?))
ビルドされた環境を利用して、Python側から学習させる。ML-AgentsのPythonAPIを用いて

Unity Environment
---
Environmentを作成する。
使用するオブジェクトは大まかに3つ

##### Academy
環境を制御する
##### Brain
エージェントの推論と行動を制御する
##### Agent
エージェントを制御する

### Academy

##### 1.オブジェクトの作成
空のオブジェクトを1つ作成する。

##### 2.スクリプトの作成
スクリプトを1つ作成して、以下のようにする。

```csharp
using MLAgents;

public class AnyAcademy : Academy
{
}
```

MLAgentsをimportして、Academyクラスを継承する。

### Brain

ProjectビューのCreateからML-Agentsを選び、適当なBrainを選ぶ。(通常LearningBrain)

### Agent

##### 1.オブジェクトの作成
エージェントとなるオブジェクトを作成する。

##### 2.スクリプトの作成
スクリプトを1つ作成して、以下のようにする。

```csharp
using MLAgents;

public class AnyAgent : Agent
```

##### 3.エージェント化
いくつかのメソッドをoverrideする。

###### void AgentReset()

エージェントの初期化や状態のリセットを行うメソッド

```csharp
public override void AgentReset()
{
    if ( this.transform.position.y < 0 )
    {
        this.rBody.angularVelocity = Vector3.zero;
        this.rBody.velocity = Vector3.zero;
        this.transform.position = new Vector3(0, 0.5f, 0);
    }

    Target.position = new Vector3(Random.value*8-4, 0.5f, Random.value*8-4);
}
```

###### void CollectObservations()

環境を観測し、状態を取得するメソッド

- AddVectorObs(state);
    - stateに状態を入れる

```csharp
public override void CollectObservations()
{
    // Target Agent の位置を取得
    AddVectorObs(Target.position);
    AddVectorObs(this.transform.position);
    // Agent の速度を取得
    AddVectorObs(rBody.velocity.x);
    AddVectorObs(rBody.velocity.z);
}
```


###### void AgentAction()
エージェントの行動をBrainから取得し、行動させる。また、報酬の設計も行う

- SetReward(reward)
    - rewardで報酬を決定する

- Done()
    - doneを決定する

```csharp
public override void AgentAction(float[] vectorAction, string textAction)
{
    Vector3 controlSignal = Vector3.zero;
    controlSignal.x = vectorAction[0];
    controlSignal.z = vectorAction[1];
    rBody.AddForce(controlSignal * speed);

    // targetとの距離
    float distanceToTarget = Vector3.Distance(this.transform.position, Target.position);

    // Targetに接触した場合
    if ( distanceToTarget < 1.4f )
    {
        SetReward(1);
        Done();
    }

    // プラットフォームから転落した場合
    if ( this.transform.position.y < 0 )
    {
        Done();
    }
}
```