かくれんぼのやつが動かない
Unityの機械学習「ML-Agents」を使ったサンプル「Hide」これがエラーするわ動かないわで大変だった
これが動くようになったので、そこまでの記録を残します
追記:動くまでの話であって、機械学習のところまで至ってません
ダウンロード
データセット
このサイトの下の方にあるGitHub
Hide
この「いいね!」マークの上にあるリンクからダウンロードします↑
このページに飛びます↓
んでダウウンロード↓
「Clone or download」
このセットの中に色々入ってますので
ドキュメントなり普段unityプロジェクトを保存している場所なりに解凍してください
Json.net
JSON.net
Newtonsoft.json(JSON使うためのもの)をダウンロードしていない人はこちらも後で必要になるので
↓一番上の「Json120r3.zip」だけで大丈夫です
適当にダウンロードして適当に解凍してください
後で必要になります
Unity
UnityHubを起動し、「リストに追加」
先ほど解凍した
hide-escape-master の中の unity-environment を選択
これで↓「フォルダの選択」
こうなる
噂によるとバージョンは2018.4以上がいいそうなので
2018.4.16をインストール
こんな感じで↓バージョン変更して開く
ウィンドウ出ますが「確認」押してGO
例のブツをみてみよう
↑の「Hide」というシーンを開く
これですよこれ 見たかったのは
~ライティングをOFFにしておく~
本編に特別関係ないけど、何かあるたび光の当たり方を計算されるのはストレスなので、機能をオフにする
開いたウィンドウ↓の一番下にある「Auto Generate」のチェックを外し
「Genaerate Lighting」ボタンを押す
とりあえずエラー
下2つはBlenderインストールしてれば何か違うのかもしれませんが、入ってないのでパス
左上の「Clear」押しても消えないエラーに対処していきます
Json.netをプラグインに入れる
ダウンロードした「Json120r3」の
Json120r3 → Bin → net20 → Newtonsoft.Json.dll を以下の場所にコピペ
参考文献
Unityでセットアップ
参考文献
Project Settingの
Playerの
other Settingを開き
ちょっと下の方
この
「ENABLE_TENSORFLOW;UNITY_POST_PROCESSING_STACK_V1」
を
「ENABLE_TENSORFLOW」
に変更↓
しかしエラーは減らない
んんんんんんんんんんんん
まあ必要な項目ではあったはずなので、エラーが消えるための設定ではなかっただけでしょう
パッケージを入れませう
なんか言ってた
適当なところにダウンロードし、「Import package」でダウンロードしたファイルを指定する
そしたらウインドウでるから、右下の「Import」ボタンをクリック
驚きの白さ
なんだか様子が変です
「HideBrain」を選択すると
なんか言ってる ファイルがねぇ と
これで動くぜ ヒャッハー!
赤おっっっっせぇぇぇぇ
なんじゃあの移動速度はぁぁぁ一生追いつけんわぁぁぁ
赤を早くさせる
「Academy」を選択
「Value」の値を「3」とかにします(お好みで)
こんだけ早ければいいだr…
いまUターンしなかった?
これで盲目の追跡者
が完成しましたね✨(コナン君の映画のタイトルにありそう)
次は赤に視界を設けます
※Blenderが入っていないために、視界のモデル(扇形↓)が生成できなかったと思われ
プログラム的には、
視線上にいる
→扇の当たり判定作動
→青を追いかける
ってなってるので、
扇の代わりを作ればおk
つまり、シーンにいる各9人に視界を設けるだけ!!
こんな時のためのプレハブ機能!!
視界を作る
仕方ないので方法は2通り
・先を見越して「Chaser」をプレハブに置き換える
・9人の「Chaser」に当たり判定を設ける
選ばれたのは後者でした
やり方は簡単
1. 全ての「fov-shape」を同時選択
2. 位置調整
3. メッシュとコライダーを設定
1.全ての「fov-shape」を同時選択
2. 位置調整
3. メッシュとコライダーを設定
Mesh Filter の「Mesh」に「Cube」を選択
Mesh Collider の「Mesh」に「Cube」を選択
できた
仁王立ちの追跡者
赤の横を青がスルッと通りすぎると以下のように、到達点で停止するバグが判明
プログラムに工夫が必要
「HideChaser」を開き
グローバル変数を宣言
float timer = 0;
Vector3 pos;
Update()の中に以下を追加
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;
応急処置ですがこれでなんとかなります
一応全文載せておきます↓
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」にすると脱出口が現れるようになります
黄色の四角いやつ
あとはがんばって
動いたはいいけど、果たして機械学習しているのか まだわかってない
追記:機械学習は十中八九至ってません。なぜならPythonとかの設定をした覚えがないからです。
追記
色々なサイトを見てもML-Agentsのデータの「UnitySDK」を使うとか書いてあるけど、使用したデータにはなくて困ってた
んで見つけた
Unity ML-Agents Toolkit v0.8:実際のゲームでより迅速なトレーニングが可能に
「ML-Agents tool kit」とかで検索してたら違うデータが出てきた
UnitySDK入ってる別のデータ
ここ
これで機械学習始められる のかな?