- 投稿日:2020-09-11T22:40:41+09:00
Unity ML-Agents の環境構築からサンプルを動かすまで
こんにちは。ネストビジュアルの西田です。最近機械学習の勉強をちょこちょこしてるのですが、Unityでも ML-Agentsを使えば強化学習ができるということでインストールしてサンプルを動かすまでやってみました。
環境
- Windows10
- Python3.7(Anaconda4.7.12) ※ML-agnetsの使用にはPython3.6.1以上が必要です
- Unity 2019.1.2f1
- ML-Agents (Release3)
Anaconda, Unity, ML-Agentsのインストール
Anacondaはこちらからインストールできます。
※インストールする際に"Add Anaconda to the system PATH environment variable"にチェックを入れておくと、後でパスを通す必要がなくなります。UnityはこちらからUnity Hubをインストールした後、Unity Hubから任意のバージョンのUnityをインストールします。
ML-Agentsはこちらの"Releases & Documentation"の所からzipをDLし、任意のディレクトリに展開します。
Pythonの仮想環境構築
AnacondaをインストールしただけではPowerShellからcondaコマンドは使えません。
まずはcondaコマンドを使えるようにするために以下のコマンドを実行します。conda create -n ml-agents python=3.7一度PowerShellを終了し、再度管理者権限で起動します。再起動後に以下のコマンドを実行すると、次回からは通常通り起動できます。
Set-ExecutionPolicy RemoteSigned次に以下のコマンドを実行してML-Agentsの仮想環境を作成し起動します。
# 仮想環境の作成 conda create -n ml-agents python=3.7 # 仮想環境の起動 conda activate ml-agentsml-agents-release_3ディレクトリに移動し、以下のコマンドを実行します。
pip install -e ./ml-agents-envs pip3 install -e ./ml-agentsこれで仮想環境は準備できました。
Unityプロジェクトの準備
Unityの新規プロジェクトを3Dで作成します。
エディタが起動したらツールバーのWindowからPackage Managerを起動し、+ボタンを押下してAdd package from diskを選択します。
~\ml-agents-release_3\com.unity.ml-agents\package.jsonを選択してインポートします。
エディタのPackagesディレクトリ以下にML-Agentsディレクトリができます。
次に~\ml-agents-release_3\Project\Assets\にあるML-AgentsディレクトリをプロジェクトのAssetsディレクトリ配下にコピーします。これでサンプルを使えるようになります。
サンプルを動かす
プロジェクトのAssets/ML-Agents/Examples/3DBall/Sceneディレクトリから3DBallを開きます。
学習はコマンドで実行します。PowerShellで以下のコマンドを実行します。idはrunするごとに変更します。数字でなくても良いので、後からわかるような文字列を指定します。
mlagents-learn ./config/ppo/3DBall.yaml --run-id=1通常はこれで学習が開始されますが、私の環境では以下のエラーが出ました。
ERROR: After October 2020 you may experience errors when installing or updating packages. This is because pip will change the way that it resolves dependency conflicts. We recommend you use --use-feature=2020-resolver to test your packages with the new resolver before it becomes the default. tensorflow 2.3.0 requires numpy<1.19.0,>=1.16.0, but you'll have numpy 1.19.0 which is incompatible.tensorflow2.3.0ではnumpy1.19.0が使えないということなので、一度numpyをアンインストールしてnumpy1.18.0をインストールしました。
# numpyをアンインストール pip3 uninstall numpy # numpy 1.18.0をインストール pip3 install numpy==1.18.0これで学習を開始できます。もう一度以下コマンドを実行します。
mlagents-learn ./config/ppo/3DBall.yaml --run-id=1コマンドが実行されると、PowerShellに以下のようにログが表示されます。
その後すぐに以下のように表示されるので、UnityエディタのPlayボタンを押すと学習が開始されます。
INFO [environment.py:199] Listening on port 5004. Start training by pressing the Play button in the Unity Editor.初めはボールが落ちていましたが、学習するにつれボールが落下しなくなります。
before
after
学習中はPowerShellにStep(学習の試行回数)のログが出ます。
~\ml-agents-release_3\config\ppoにある3DBall.yamlでは、最大ステップ数が5,00,00回になっています。
ログを確認しながら、ステップ数が5,00,00回に達したらUnityエディタの停止ボタンを押して学習を終了します。おわりに
ML-Agentsを使用すれば割と簡単に強化学習を体験できることがわかりました。今回はサンプルを動かしただけですが、今後自分でモデルを作る所までやってみようと思います。
- 投稿日:2020-09-11T22:08:53+09:00
Unityで録音して、録音したサウンドを再生する最小実装
Unityでサウンドを録音して、また録音した音声を再生させた事がなかったので調査しました。
録音開始
MicrophoneクラスをStartすると録音状態となります。
// 10・・・録音最大秒数 // 44100・・・サンプリング周波数 _recordedClip = Microphone.Start("(録音機材名)", false, 10, 44100);そして録音を終了する、または録音最大時間を越えると戻り値に録音済みのAudioClipが返却されます。使い方はとってもシンプルです。
録音する際は録音機材名の指定が必要です。上記のソースコードの中の
"(録音機材名)"
の部分です。録音機材名の取得
Microphone.devices
配列から録音機材名を取得できます。foreach (string device in Microphone.devices) { // 録音機材名リストに保持 _micNames.Add(device); }録音の終了
Microphone.End("(録音機材名)");ちなみに録音の終了は、Endメソッドに使用したデバイス名をセットします。
成果物
OnGUIで超シンプルなUIをデバッグ用として用意しています。
僕のMacはSoundfloowerをインストールしているので、マイクが複数あり、それに気づかず最初動作しなくて戸惑いました。なぜこんな事をしているか?
経緯としては、子供がトランシーバーがほしいとせがんでくるため、家にあるものでそれっぽいものが作れないか今まさに模索している最中でございます。以下経緯Tweet。
子供がどうしてもトランシーバーが欲しいと言われて、なんとか家にあるもので同様のものが作れないか模索している、ポーリングでなんとか出来ないかな。。
— 大庭俊介@UXエンジニア (@ohbashunsuke) September 11, 20202台のスマホアプリで音声を直接やり取りする、またはサーバーに一旦保持させるなど、やり方は色々ありそうです。
どちらにしても声の録音が必要だったので備忘録として残しました。
Unityじゃなくても良いのだが..
そうです。Unityでやる必要は一切ありません。しかしiOS、Androidに両方ビルドできるメリット、僕が Unityに慣れているという点、納期が短い(明日子供が学校から返ってくるまで)という点から採用しています。
時間が許せば、最近気になっているFlutterで実装し直してみようと思います。
全ソースは以下にアップしています。
https://gist.github.com/baobao/4e5d1332e030828d141c492f93ea3c06
- 投稿日:2020-09-11T18:27:01+09:00
ML-Agentsでカートポールを実装2
はじめに
前回の記事の続きです。今回は作成した3Dオブジェクトを動かすスクリプトを書いていきます。
エージェントのスクリプトを記述する
今回はカートポールのカートに力を加えてポールを制御していきます。つまり、カートが学習させるエージェントになります。
まず初めにScriptフォルダにCartPoleAgentというC# Scriptを作成してください。エージェントのスクリプトではAgentクラスを継承し、以下の関数を記述します。
- Initialize() : 初期値を取得
- CollectObservations() : 観測データをセンサーに送る
- OnActionReceived() : 行動する
- OnEpisodeBegin() : ステップ開始の条件を決定
- Heuristic() : キーボードから操作する
- SetResetParameters() : パラメータをリセット
CartPoleAgent.csの全体
はじめにスクリプトの全体のコードを載せます。
using UnityEngine; using Unity.MLAgents; using Unity.MLAgents.Sensors; using System.Collections; using System.Collections.Generic; public class CartPoleAgent : Agent { //学習用 public GameObject pole; Rigidbody poleRB; Rigidbody cartRB; EnvironmentParameters m_ResetParams; //初期値 public override void Initialize() { //学習の初期化 poleRB = pole.GetComponent<Rigidbody>(); cartRB = gameObject.GetComponent<Rigidbody>(); m_ResetParams = Academy.Instance.EnvironmentParameters; SetResetParameters(); } //センサーにデータを送る public override void CollectObservations(VectorSensor sensor) { sensor.AddObservation(gameObject.transform.localPosition.z); sensor.AddObservation(cartRB.velocity.z); sensor.AddObservation(pole.transform.localRotation.eulerAngles.x); sensor.AddObservation(poleRB.angularVelocity.x); } //各ステップでの行動 public override void OnActionReceived(float[] verctorAction) { //カートに力を加える var actionZ = 200f * Mathf.Clamp(verctorAction[0], -1f, 1f); cartRB.AddForce(new Vector3(0.0f, 0.0f, actionZ), ForceMode.Force); //カートの位置、ポールの角度と角速度 float cart_z = this.gameObject.transform.localPosition.z; float angle_x = pole.transform.localRotation.eulerAngles.x; //angle_zを-180~180に変換 if(180f < angle_x && angle_x < 360f) { angle_x = angle_x - 360f; } //カートが+-45度いないなら報酬+0.1 それ以外は -1 if((-180f < angle_x && angle_x < -45f) || (45f < angle_x && angle_x < 180f)) { SetReward(-1.0f); EndEpisode(); } else{ SetReward(0.1f); } //カートの位置が-10~10の範囲を超えたら報酬-1 if(cart_z < -10f || 10f < cart_z) { SetReward(-1.0f); EndEpisode(); } } //ステップ開始の初期条件を決定 public override void OnEpisodeBegin() { //エージェントの状態をリセット gameObject.transform.localPosition = new Vector3(0f, 0f, 0f); pole.transform.localPosition = new Vector3(0f, 2.5f, 0f); pole.transform.localRotation = Quaternion.Euler(0f, 0f, 0f); poleRB.angularVelocity = new Vector3(0f, 0f, 0f); poleRB.velocity = new Vector3(0f, 0f, 0f); //ポールにランダムな傾きを与える poleRB.angularVelocity = new Vector3(Random.Range(-0.1f, 0.1f), 0f, 0f); SetResetParameters(); } //キーボードから操作する場合 public override void Heuristic(float[] actionsOut) { actionsOut[0] = Input.GetAxis("Horizontal"); } //ポールの条件をリセット public void SetPole() { poleRB.mass = m_ResetParams.GetWithDefault("mass", 1.0f); pole.transform.localScale = new Vector3(0.4f, 2f, 0.4f); } //パラメータをリセットする関数 public void SetResetParameters() { SetPole(); } }public class CartPoleAgent : AgentAgentクラスを継承します。
public GameObject pole; Rigidbody poleRB; Rigidbody cartRB; EnviromentParameters m_ResetParams;で PoleオブジェクトやCart, Pole の rigidbody をいれる変数を定義します。Poleオブジェクトはスクリプト外から取得するので public にします。
Initialize()
Initialize()では学習の初期値を取得します。今回はCart と Pole のrigidbody と環境のパラメータです。また最後の行で各パラメータをリセットしています。
public override void Initialize() { //学習の初期化 poleRB = pole.GetComponent<Rigidbody>(); cartRB = gameObject.GetComponent<Rigidbody>(); m_ResetParams = Academy.Instance.EnvironmentParameters; SetResetParameters(); }CollectObservations()
CollectionObservations()ではエージェントが得た観測情報をセンサーに追加します。
public override void CollectObservations(VectorSensor sensor) { sensor.AddObservation(gameObject.transform.localPosition.z); sensor.AddObservation(cartRB.velocity.z); sensor.AddObservation(pole.transform.localRotation.eulerAngles.x); sensor.AddObservation(poleRB.angularVelocity.x); }今回は上から、「Cartの位置」、「Cartの速度」、「Poleの角度」、「Poleの角速度」を与えています。
この値の選択は学習モデルによって変わります。この値が適切なのかわからないので、いろいろ試してみてください。OnActionReceived()
OnActionReceived()では各ステップでのエージェントの動きについて記述します。今回はカートに移動方向の力を加えます。
また、報酬の設定などもここで行います。//各ステップでの行動 public override void OnActionReceived(float[] verctorAction) { //カートに力を加える var actionZ = 200f * Mathf.Clamp(verctorAction[0], -1f, 1f); cartRB.AddForce(new Vector3(0.0f, 0.0f, actionZ), ForceMode.Force); //カートの位置、ポールの角度と角速度 float cart_z = this.gameObject.transform.localPosition.z; float angle_x = pole.transform.localRotation.eulerAngles.x; //angle_zを-180~180に変換 if(180f < angle_x && angle_x < 360f) { angle_x = angle_x - 360f; } //カートが+-45度いないなら報酬+0.1 それ以外は -1 if((-180f < angle_x && angle_x < -45f) || (45f < angle_x && angle_x < 180f)) { SetReward(-1.0f); EndEpisode(); } else{ SetReward(0.1f); } //カートの位置が-10~10の範囲を超えたら報酬-1 if(cart_z < -10f || 10f < cart_z) { SetReward(-1.0f); EndEpisode(); } }カートを動かすコードです。入力値がvectorActionになっています。この値を -200~200 に変換し、加える力の大きさにします。この値の幅は適当です。CartのrigidbodyのAddForceをいじることでカートに力を加えることができます。今回はZ方向に力を加えます。
//カートに力を加える var actionZ = 200f * Mathf.Clamp(verctorAction[0], -1f, 1f); cartRB.AddForce(new Vector3(0.0f, 0.0f, actionZ), ForceMode.Force);エージェント(カート)の報酬に関するコードです。今回はポールの角度が -45°~45° 以内だと報酬として +0.1, それ以外だと報酬を -1.0 与えゲームを終了させます。また、カートが横に動きすぎないようにカートの位置が -10~10 の範囲から出ると -1.0 の報酬を与えゲームを終了させます。
//カートが+-45度いないなら報酬+0.1 それ以外は -1 if((-180f < angle_x && angle_x < -45f) || (45f < angle_x && angle_x < 180f)) { SetReward(-1.0f); EndEpisode(); } else{ SetReward(0.1f); } //カートの位置が-10~10の範囲を超えたら報酬-1 if(cart_z < -10f || 10f < cart_z) { SetReward(-1.0f); EndEpisode(); }OnEpisodeBegin()
OnEpisodeBegin()ではゲームの初期条件を決めます。今回はカートは初期位置に戻し、ポールにランダムな傾きを与えます。
//ステップ開始の初期条件を決定 public override void OnEpisodeBegin() { //エージェントの状態をリセット gameObject.transform.localPosition = new Vector3(0f, 0f, 0f); pole.transform.localPosition = new Vector3(0f, 2.5f, 0f); pole.transform.localRotation = Quaternion.Euler(0f, 0f, 0f); poleRB.angularVelocity = new Vector3(0f, 0f, 0f); poleRB.velocity = new Vector3(0f, 0f, 0f); //ポールにランダムな傾きを与える poleRB.angularVelocity = new Vector3(Random.Range(-0.1f, 0.1f), 0f, 0f); SetResetParameters(); }Heuristic()
Heuristic()ではキーボード入力でモデルを動かすときに使用します。今回は十字キーの左右の入力に対応しています。
//キーボードから操作する場合 public override void Heuristic(float[] actionsOut) { actionsOut[0] = Input.GetAxis("Horizontal"); }Behavior Parametersの設定、実際に動かしてみる
このスクリプトをCartオブジェクトに追加してください。このときPoleにPoleオブジェクトを追加してください。
また、Add Component から、Behavior Parameters と Decision Requester を追加してください。これは強化学習時に必要になります。Behavior Parameters / Behavior Type でモデルのモードを変更することができます。今回はキーボード入力を使用したいので Heuristic Only にしてください。学習時は Defaults, 学習済みモデルを使用するときは Inference Only にします。(Inference Onlyを使用する場合は学習済みモデルをModelに追加する必要があります。)
以下の画像のようにパラメータを設定してください。
この状態でモデルを実行するとキーボードで操作することができると思います。しっかり、ポールの角度でリセットされていればOKです。
ここまでで学習に必要な準備は完了しました。あとはサンプルと同じように学習されれば完成になります。
学習させる
実際にカートポールを学習させます。学習させるため、Behavior Parameters / Behavior Type を Defaults にしてください。
また学習の効率化のためカートポールを複数台にします。今回は10台にしました。コピペで簡単に増やすことができます。
学習パラメータを設定するYAMLファイルをconfigフォルダに作成してください。3DBallのパラメータを参考にしました。
モデルの学習方法の詳しい解説はこの記事を参考にしてください。
25万回ぐらいで学習が完了します。学習が完了すると CartPole.nn というファイルが作成されています。このファイルを TFModels に追加してください。
TrainingArea(1)~(9)を非アクティブにして学習済みモデルを実行した動画です。ポールを倒さないように制御できていることが確認できます。
まとめ
カートポールのモデルを作成し、学習させませた。ML-Agentsでは基本的にエージェントのスクリプトを書くだけで強化学習モデルを簡単に実装することができます。まだわからないことが多いので知識が増えたらまた記事を書きたいと思います。
- 投稿日:2020-09-11T17:43:01+09:00
TextMeshProでアンダーラインが表示されない時の対処方法
起きたこと
TextMeshProで、FontStyleにUnderlineを指定しても、アンダーラインが表示されませんでした。
原因と対処法
TextMeshProではアンダーラインを表示するために、
_
(アンダースコア)を使っているため、生成したフォントアトラスに_
が含まれていないとアンダーラインを表示できません。
Window>Text Mesh Pro>Font Asset Creator>Custom Character List
へ_
を追加してからフォントアトラスを生成すると解決しました。参考文献
TextMesh Pro - TMP Fallback font underline bug - Unity Forum
- 投稿日:2020-09-11T15:43:20+09:00
ML-Agentsでカートポールを実装2
概要
ML-Agentsでカートポールを実装し、学習させます。自分でML-Aegentsを使って学習させるモデルを作成したい人の助けになればいいと思っています。
はじめに
ML-Agentsのサンプルのようなモデルを自作します。学習方法は前回の記事で説明したので、今回は学習させるモデルの作り方を中心に記事にしました。公式のドキュメントを参考にしました。細かいところはこちらを確認してください。
全体の流れ
モデルの作成、学習には主に4つ工程があります。
- unityで3Dモデルを作成
- 学習させるエージェントのスクリプトを記述する
- Behavior Parameterを設定する
- 学習させる
実際に作成しながら説明していきます。
記事が長くなるので今回は3Dモデルの作成まで説明します。unityで3Dモデルを作成
はじめにunityで学習させたい3Dモデルを作成します。今回はカートポールを実装します。カートポールとはカートについているポールが倒れないように制御する問題のことです。
最終的には以下のモデルを作成します。学習を効率化するために複数のモデルを置いてます。
カートポール作成
左下のProjectで以下の画像のようにCartPoleというファイルを作成してください。また、File/New Sceneから新しいシーンを作成しCart Poleと名付けて作成したファイルに保存してください。
Materialにはカートやポール、床の材料特性を設定するものが入ります。Scriptには作成したオブジェクトを動かすスクリプトが入ります。最後のTFModelsは学習済みモデルを入れるファイルになります。次にsceneを開いて以下のように3D Objectを追加してください。
追加する3D Objectは cube, sylinder, plane をそれぞれ一つづつ追加してください。また追加したら cubeをCartに、sylinderをPoleに名前を変更してください。また、CartとPoleはTrainingAreaという空のObjectを作成し、そこに入れてください。
それぞれのスケールなどは以下の画像を参考にしてください。
次にcomponentを追加していきます。
Componentの追加
unity では作成したオブジェクトにcomponentを追加することで様々な特性を持たせることができます。今回は rigidbody と Hinge Joint を追加します。 rigidbody を追加することによって、オブジェクトを物理特性によって制御することができるようになります。具体的には重力を付加したり、力を加えたり、空気抵抗などを設定することができます。Hinge Joint を追加するとCart と Pole がヒンジで結合されます。
componentの追加方法は、追加したいオブジェクトを選択し、画面の右下にある Add Component をクリックし追加したい物を選択します。
rigidbodyの追加
「rigidbody」を選択します。
CartとPoleにそれぞれ追加してください。追加されると以下の画像のようになると思います。
パラメータをそれぞれ画像のように設定してください。(適当でもいいです)
Mass はオブジェクトの質量[Kg]です。
Drag は空気抵抗を表しています。値が大きくなるほど抵抗が大きくなります。0の場合は真空状態となります。
Angular Drag はオブジェクトが回転する時の空気抵抗です。値が大きいほど回転しにくくなります。
Constraints / Freeze Position はオブジェクトの動きを制限させます。今回Cartは横方向(Z方向)に動いて欲しいので、手前方向(X方向)にチェックを入れます。
Freeze Rotation はオブジェクトの回転を制限します。今回はCartは回転しないので全てにチェックを入れてください。
Hinge Joint の追加
Add Component / Physics / Hinge Joint から追加してください。
パラメータを画像のように設定してください。また Connected Body に Cart を追加してください。Materialの設定
次にオブジェクトのMaterialの設定をします。Cart と Pole は色を設定するだけなので各自設定してください。今回はPlaneで摩擦を設定します。Materialフォルダの中にPhysic Material を追加して、Planeという名前に変更してください。真ん中の黄緑色のやつができると思います。
Dynamic Friction で動摩擦を設定します。値は 0~inf で大きいほどオブジェクトが動かなくなります。
Static Friction は静止摩擦を設定します。
今回摩擦のパラメータは適当でいいです(大きすぎるとCartが動かなくなります)。作成した Physic Material を Plane オブジェクトに追加してください。Planeオブジェクトを選択し、そこにドラッグアンドドロップすればいいです。画像の印のようになっていればOKです。
これで3Dオブジェクトは完成になります。
まとめ
今回はunityで3DオブジェクトのCart Pole を作成しました。これで学習させるモデルはほぼ完成しました。次回はスクリプトを書いていきます。
- 投稿日:2020-09-11T15:43:20+09:00
ML-Agentsでカートポールを実装1
概要
ML-Agentsでカートポールを実装し、学習させます。自分でML-Aegentsを使って学習させるモデルを作成したい人の助けになればいいと思っています。
はじめに
ML-Agentsのサンプルのようなモデルを自作します。学習方法は前回の記事で説明したので、今回は学習させるモデルの作り方を中心に記事にしました。公式のドキュメントを参考にしました。細かいところはこちらを確認してください。
全体の流れ
モデルの作成、学習には主に4つ工程があります。
- unityで3Dモデルを作成
- 学習させるエージェントのスクリプトを記述する
- Behavior Parameterを設定する
- 学習させる
実際に作成しながら説明していきます。
記事が長くなるので今回は3Dモデルの作成まで説明します。unityで3Dモデルを作成
はじめにunityで学習させたい3Dモデルを作成します。今回はカートポールを実装します。カートポールとはカートについているポールが倒れないように制御する問題のことです。
最終的には以下のモデルを作成します。学習を効率化するために複数のモデルを置いてます。
カートポール作成
左下のProjectで以下の画像のようにCartPoleというフォルダを作成してください。また、File/New Sceneから新しいシーンを作成しCart Poleと名付けて作成したフォルダに保存してください。
Materialにはカートやポール、床の材料特性を設定するものが入ります。Scriptには作成したオブジェクトを動かすスクリプトが入ります。最後のTFModelsは学習済みモデルを入れるフォルダになります。次にsceneを開いて以下のように3D Objectを追加してください。
追加する3D Objectは cube, sylinder, plane をそれぞれ一つづつ追加してください。また追加したら cubeをCartに、sylinderをPoleに名前を変更してください。また、CartとPoleはTrainingAreaという空のObjectを作成し、そこに入れてください。
それぞれのスケールなどは以下の画像を参考にしてください。
次にcomponentを追加していきます。
Componentの追加
unity では作成したオブジェクトにcomponentを追加することで様々な特性を持たせることができます。今回は rigidbody と Hinge Joint を追加します。 rigidbody を追加することによって、オブジェクトを物理特性によって制御することができるようになります。具体的には重力を付加したり、力を加えたり、空気抵抗などを設定することができます。Hinge Joint を追加するとCart と Pole がヒンジで結合されます。
componentの追加方法は、追加したいオブジェクトを選択し、画面の右下にある Add Component をクリックし追加したい物を選択します。
rigidbodyの追加
「rigidbody」を選択します。
CartとPoleにそれぞれ追加してください。追加されると以下の画像のようになると思います。
パラメータをそれぞれ画像のように設定してください。(適当でもいいです)
Mass はオブジェクトの質量[Kg]です。
Drag は空気抵抗を表しています。値が大きくなるほど抵抗が大きくなります。0の場合は真空状態となります。
Angular Drag はオブジェクトが回転する時の空気抵抗です。値が大きいほど回転しにくくなります。
Constraints / Freeze Position はオブジェクトの動きを制限させます。今回Cartは横方向(Z方向)に動いて欲しいので、手前方向(X方向)にチェックを入れます。
Freeze Rotation はオブジェクトの回転を制限します。今回はCartは回転しないので全てにチェックを入れてください。
Hinge Joint の追加
Add Component / Physics / Hinge Joint から追加してください。
パラメータを画像のように設定してください。また Connected Body に Cart を追加してください。Materialの設定
次にオブジェクトのMaterialの設定をします。Cart と Pole は色を設定するだけなので各自設定してください。今回はPlaneで摩擦を設定します。Materialフォルダの中にPhysic Material を追加して、Planeという名前に変更してください。真ん中の黄緑色のやつができると思います。
Dynamic Friction で動摩擦を設定します。値は 0~inf で大きいほどオブジェクトが動かなくなります。
Static Friction は静止摩擦を設定します。
今回摩擦のパラメータは適当でいいです(大きすぎるとCartが動かなくなります)。作成した Physic Material を Plane オブジェクトに追加してください。Planeオブジェクトを選択し、そこにドラッグアンドドロップすればいいです。画像の印のようになっていればOKです。
これで3Dオブジェクトは完成になります。
まとめ
今回はunityで3DオブジェクトのCart Pole を作成しました。これで学習させるモデルはほぼ完成しました。次回はスクリプトを書いていきます。