LoginSignup
1
2

More than 3 years have passed since last update.

[Unity]ML-Agents「Hide / Escape - Avoidance of Pursuing Enemies」を動かすまで

Last updated at Posted at 2020-02-11

かくれんぼのやつが動かない

Unityの機械学習「ML-Agents」を使ったサンプル「Hide」これがエラーするわ動かないわで大変だった
image.png

これが動くようになったので、そこまでの記録を残します
追記:動くまでの話であって、機械学習のところまで至ってません

ダウンロード

データセット

このサイトの下の方にあるGitHub
Hide
image.png
この「いいね!」マークの上にあるリンクからダウンロードします↑

このページに飛びます↓
image.png
んでダウウンロード↓
「Clone or download」
image.png

zipでお好みの場所に保存(どこでも)
image.png

このセットの中に色々入ってますので
image.png
ドキュメントなり普段unityプロジェクトを保存している場所なりに解凍してください

Json.net

JSON.net
Newtonsoft.json(JSON使うためのもの)をダウンロードしていない人はこちらも後で必要になるので
↓一番上の「Json120r3.zip」だけで大丈夫です
image.png
適当にダウンロードして適当に解凍してください
後で必要になります

Unity

UnityHubを起動し、「リストに追加」
image.png
先ほど解凍した
hide-escape-master の中の unity-environment を選択
これで↓「フォルダの選択」
image.png

こうなる
asdfjkdalfj.png
噂によるとバージョンは2018.4以上がいいそうなので
image.png2018.4.16をインストール

こんな感じで↓バージョン変更して開く
asdfjkdalfj.png
ウィンドウ出ますが「確認」押してGO
image.png

例のブツをみてみよう

image.png
↑の「Hide」というシーンを開く
image.png
これですよこれ 見たかったのは

~ライティングをOFFにしておく~

本編に特別関係ないけど、何かあるたび光の当たり方を計算されるのはストレスなので、機能をオフにする
image.png
開いたウィンドウ↓の一番下にある「Auto Generate」のチェックを外し
image.png
「Genaerate Lighting」ボタンを押す
image.png

とりあえずエラー

image.png
下2つはBlenderインストールしてれば何か違うのかもしれませんが、入ってないのでパス
左上の「Clear」押しても消えないエラーに対処していきます
image.png

Json.netをプラグインに入れる

ダウンロードした「Json120r3」の
Json120r3 → Bin → net20 → Newtonsoft.Json.dll を以下の場所にコピペ
image.png
参考文献

するとエラーは3つ
image.png

Unityでセットアップ

参考文献
image.pngProject Settingの
image.pngPlayerの
image.pngother Settingを開き
image.pngちょっと下の方

この
「ENABLE_TENSORFLOW;UNITY_POST_PROCESSING_STACK_V1」

「ENABLE_TENSORFLOW」
に変更↓
image.png

image.png
しかしエラーは減らない
んんんんんんんんんんんん
まあ必要な項目ではあったはずなので、エラーが消えるための設定ではなかっただけでしょう

パッケージを入れませう

なんか言ってた
image.png
適当なところにダウンロードし、「Import package」でダウンロードしたファイルを指定する
image.png
そしたらウインドウでるから、右下の「Import」ボタンをクリック
image.png
image.png
驚きの白さ

なんだか様子が変です

「HideBrain」を選択すると
image.pngimage.png
なんか言ってる ファイルがねぇ と

なのでこの「Hide3-3M」を指定してあげます
image.png
image.png

これで動くぜ ヒャッハー!

ダウンロード.gif
赤おっっっっせぇぇぇぇ
なんじゃあの移動速度はぁぁぁ一生追いつけんわぁぁぁ

赤を早くさせる

「Academy」を選択
image.pngimage.png
「Value」の値を「3」とかにします(お好みで)
ダウンロード.gifこんだけ早ければいいだr…

いまUターンしなかった?

これで盲目の追跡者が完成しましたね✨(コナン君の映画のタイトルにありそう)
次は赤に視界を設けます
※Blenderが入っていないために、視界のモデル(扇形↓)が生成できなかったと思われ
image.png

プログラム的には、
視線上にいる
→扇の当たり判定作動
→青を追いかける
ってなってるので、
扇の代わりを作ればおk

つまり、シーンにいる各9人に視界を設けるだけ!!
こんな時のためのプレハブ機能!!

image.png※尚、プレハブではない
ど う し て

視界を作る

仕方ないので方法は2通り
・先を見越して「Chaser」をプレハブに置き換える
・9人の「Chaser」に当たり判定を設ける

選ばれたのは後者でした

やり方は簡単
1. 全ての「fov-shape」を同時選択
2. 位置調整
3. メッシュとコライダーを設定

1.全ての「fov-shape」を同時選択

「Ctrl」を押しながら、各fov-shapeをクリック
image.png

2. 位置調整

以下のように値を調整
image.pngimage.png

3. メッシュとコライダーを設定

Mesh Filter の「Mesh」に「Cube」を選択
image.png
Mesh Collider の「Mesh」に「Cube」を選択
image.png

するとこうなる
image.png

できた

AIi.gif

仁王立ちの追跡者

赤の横を青がスルッと通りすぎると以下のように、到達点で停止するバグが判明
image.png

プログラムに工夫が必要
「HideChaser」を開き
グローバル変数を宣言

HideChaser.cs
    float timer = 0;
    Vector3 pos;

Update()の中に以下を追加

HideChaser.cs
        if(transform.position == pos)
        {
            timer += Time.deltaTime;
            if(timer > 5)
            {
                timer = 0;
                Debug.LogWarning("Stopped");
                agentInFOV = false;
                agentInLOS = false;
                chasingAgent = false;
                PickNextRoom();
            }
        }
        else
        {
            timer = 0;
        }
        pos = transform.position;

応急処置ですがこれでなんとかなります
一応全文載せておきます↓

HideChaser.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class HideChaser : MonoBehaviour {

    public GameObject myAgent;
    public GameObject chaserHead;
    [HideInInspector]
    public HideAgent hideAgent;

    public GameObject[] seekLocations;
    private float positionDoneThreshold = 0.15f;

    public GameObject[] chaserInitialPositions;

    [HideInInspector]
    public NavMeshAgent navAgent;

    [HideInInspector]
    public GameObject currentTarget;
    public GameObject targetLocationIndicator;

    [HideInInspector]
    public bool agentInLOS = false;
    [HideInInspector]
    public bool agentInFOV = false;
    [HideInInspector]
    public bool chasingAgent = false;
    public bool showDebug = false;

    [HideInInspector]
    public Vector3 lastKnownAgentLocation;

    private Rigidbody chaserRigidbody;

    public HideAcademy hideAcademy;

    public GameObject winZone;

    float timer = 0;
    Vector3 pos;
    void Start ()
    {
        this.navAgent = this.GetComponent<NavMeshAgent>();
        this.chaserRigidbody = this.GetComponent<Rigidbody>();

        this.hideAgent = myAgent.GetComponent<HideAgent>();

        currentTarget = seekLocations[Random.Range(0, seekLocations.Length)];
        navAgent.SetDestination(currentTarget.transform.position);

        this.targetLocationIndicator.transform.parent = null;
        lastKnownAgentLocation = Vector3.zero;
        pos = transform.position;
    }

    void Update ()
    {
        PlaceTargetIndicator();
        MoveChaser();

        if(transform.position == pos)
        {
            timer += Time.deltaTime;
            if(timer > 5)
            {
                timer = 0;
                Debug.LogWarning("Stopped");
                agentInFOV = false;
                agentInLOS = false;
                chasingAgent = false;
                PickNextRoom();
            }
        }
        else
        {
            timer = 0;
        }
        pos = transform.position;
    }

    void MoveChaser()
    {
        // If Agent Has Not Been Seen
        // Pick next room upon reaching destination
        if (Mathf.Abs((currentTarget.transform.position - this.transform.position).magnitude) < positionDoneThreshold && (chasingAgent == false))
        {
            //Debug.Log("Chaser Arrived At Location: " + currentTarget);
            PickNextRoom();
        }

        // If Agent Has Been Seen
        // Pick next room upon reaching last known location
        if ((Mathf.Abs((lastKnownAgentLocation - this.transform.position).magnitude) < positionDoneThreshold) && (chasingAgent == true) && (agentInLOS == false))
        {
            //Debug.Log("Chaser Arrived At LastKnownAgentLocation");
            chasingAgent = false;
            PickNextRoom();
        }

        // If Agent is currently seen, chase
        if (chasingAgent == true)
        {
            //Debug.Log("Chase Agent");
            ChaseAgent();
        }
    }

    public void InLOS()
    {
        if (agentInFOV)
        {
            agentInLOS = true;
            chasingAgent = true;
            lastKnownAgentLocation = myAgent.transform.position;
        }
    }

    private void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject == myAgent.transform.gameObject)
        {
            HideAgent agent = myAgent.GetComponent<HideAgent>();
            agent.done = true;
            agent.reward -= 10f;
            agent.losses += 1;
        }
    }

    void PlaceTargetIndicator()
    {
        if (chasingAgent == false)
        {
            targetLocationIndicator.transform.position = currentTarget.transform.position;
        }
        else
        {
            targetLocationIndicator.transform.position = lastKnownAgentLocation;
        }
    }

    public void PickNextRoom()
    {
        GameObject tempCurrentTarget = seekLocations[Random.Range(0, seekLocations.Length)];
        while(tempCurrentTarget == currentTarget)
        {
            tempCurrentTarget = seekLocations[Random.Range(0, seekLocations.Length)];
        }
        if(tempCurrentTarget != currentTarget)
        {
            //Debug.Log("New target chosen: " + tempCurrentTarget + " Old target was: " + currentTarget);
            currentTarget = tempCurrentTarget;
            navAgent.SetDestination(currentTarget.transform.position);
            targetLocationIndicator.transform.position = currentTarget.transform.position;
        }
    }

    public void ChaseAgent()
    {
        currentTarget = myAgent;
        navAgent.SetDestination(lastKnownAgentLocation);
    }

    public void Reset()
    {
        // Get curriculum variables from academy
        float chaserSpeed = hideAcademy.GetComponent<HideAcademy>().chaserSpeed;

        // Set curriculum variables
        navAgent.speed = chaserSpeed;

        this.chaserRigidbody.isKinematic = true;

        GameObject chaserInitialPosition = chaserInitialPositions[Random.Range(0, chaserInitialPositions.Length)];

        this.transform.position = new Vector3(chaserInitialPosition.transform.position.x, this.transform.position.y, chaserInitialPosition.transform.position.z);
        this.transform.rotation = chaserInitialPosition.transform.rotation;

        if (hideAcademy.mode == HideAcademy.Mode.Escape)
        {
            if (winZone != null)
            {
                winZone.transform.position = new Vector3(chaserInitialPosition.transform.position.x, winZone.transform.position.y, chaserInitialPosition.transform.position.z);
            }
        }

        agentInLOS = false;
        chasingAgent = false;
        currentTarget = null;
        //lastKnownAgentLocation = Vector3.zero;
        this.chaserRigidbody.isKinematic = false;
        PickNextRoom();
    }
}

モード変更

「Academy」オブジェクトの「Mode」を「Escape」にすると脱出口が現れるようになります
image.png
image.png黄色の四角いやつ

あとはがんばって

動いたはいいけど、果たして機械学習しているのか まだわかってない

追記:機械学習は十中八九至ってません。なぜならPythonとかの設定をした覚えがないからです。

それでは皆さん よき機械学習を
ダウンロード.gif

追記

色々なサイトを見てもML-Agentsのデータの「UnitySDK」を使うとか書いてあるけど、使用したデータにはなくて困ってた

んで見つけた
Unity ML-Agents Toolkit v0.8:実際のゲームでより迅速なトレーニングが可能に
「ML-Agents tool kit」とかで検索してたら違うデータが出てきた
image.png
UnitySDK入ってる別のデータ
ここ

これで機械学習始められる のかな?

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2